How to Detect mousewheel Movement and Make It not Incremental - javascript

May you all have a good day Today!
I finally made my scrollable tab, but it's not what I want. Because, when I scroll up one time it moves to the previous tab in which one scroll is one movement, it's incremental. But, what I want is as much I scroll the mouse once, it changes to another tab. I already add the console.log to my code below. My reference is Fullpage JS and this landing page. Please go see it if you don't understand my explanation.
UPDATE-1 :
I already found it in another post of stackoverflow that very similar to my problem in here : Detect the number of times mouse wheel was spun and not the length it was spun. But, alvaro commented that this method not working in kinetic devices.
Please help me to get through this. So, here's my code :
//Add & remove class tab, contents, & menu onclick & wheel
window.addEventListener('DOMContentLoaded', ()=> {
let tabs = document.querySelectorAll('.tab');
let content = document.querySelectorAll('.content');
let firstTab = function(tabs) {tabs.classList.add('tab-active')};
let firstContent = function(content) {content.classList.add('content-active')};
let activeTab = 0;
firstTab(tabs[0]);
firstContent(content[0]);
for (let i = 0; i < tabs.length; i++) {
tabs[i].addEventListener('click', () => tabClick(i));
}
function detect(e) {
var delta = null,
direction = false;
if(!e) {e = window.event;}
if(e.wheelDelta) {delta = e.wheelDelta / 60;
} else if(e.detail) {delta = -e.detail / 2;}
if(delta !== null) {
direction = delta > 0 ? 'up' : 'down';}
return direction;
}
function handle(direction) { //mousewheel to change tabs
console.log(direction);
if(direction == 'down') {
if(activeTab >= tabs.length - 1) {
activeTab = 0;
tabClick(activeTab);
} else {
tabClick(activeTab + 1);
}
} else if(direction == 'up') {
if(activeTab === 0) {
activeTab = tabs.length - 1;
tabClick(activeTab);
} else {
tabClick(activeTab - 1);
}
} else {
// this means the direction of the mouse wheel could not be determined
}
}
document.onmousewheel = function(e) {handle(detect(e));};
if(window.addEventListener) {document.addEventListener
('DOMMouseScroll', function(e) {handle(detect(e));});
}
function tabClick(currentTab) {
removeActive();
//Add Active Class
tabs[currentTab].classList.add('tab-active');
content[currentTab].classList.add('content-active');
activeTab = currentTab;
}
function removeActive() {
for (let i = 0; i < tabs.length; i++) {
//Remove Active Class
content[i].classList.remove('content-active');
content[i].classList.add('content-show');
setTimeout(function() {
content[i].classList.remove('content-show');
},1500);
tabs[i].classList.remove('tab-active');
}
}
})
/* WHOLE CONTAINER */
.container {
width: 96vw;
height: 96vh;
}
/* TABS */
.tabs {
display: flex;
height: 50px;
overflow: hidden;
align-items: center;
justify-content: center;
width: 100%;
}
.tab {
font-size: 14px;
padding: 5px 10px;
cursor: pointer;
letter-spacing: 2px;
text-alignment: center;
}
#red.tab-active {background-color: rgb(245, 66, 66);}
#blue.tab-active {background-color: rgb(66, 135, 245);}
#yellow.tab-active {background-color: rgb(245, 215, 66);}
#green.tab-active {background-color: rgb(56, 235, 98);}
#cyan.tab-active {background-color: rgb(79, 247, 219);}
/* TAB CONTENTS */
.contents {
width: 100%;
margin-top: 5px;
height: 80%;
}
.content {
width: 96%;
height: 80%;
display: none;
padding: 0;
margin: 0;
border: none;
position: absolute;
}
.content-show {
display: flex;
animation-name: fade-out;
animation-duration: 2.5s;
}
#keyframes fade-out {
0% {
opacity: 1;
display: flex;
}
99% {
opacity: 0;
display: flex;
}
100% {
opacity: 0;
display: none;
}
}
.content-active {
display: flex;
border: none;
justify-content: center;
animation-name: fade-in;
animation-duration: 2.5s;
}
#keyframes fade-in {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0.01;
}
100%{
display: block;
opacity: 1;
}
}
#red.content-active {background-color: rgb(245, 66, 66);}
#blue.content-active {background-color: rgb(66, 135, 245);}
#yellow.content-active {background-color: rgb(245, 215, 66);}
#green.content-active {background-color: rgb(56, 235, 98);}
#cyan.content-active {background-color: rgb(79, 247, 219);}
<div class="container">
<div class="tabs">
<div id="red" class="tab">RED</div>
<div id="blue" class="tab">BLUE</div>
<div id="yellow" class="tab">YELLOW</div>
<div id="green" class="tab">GREEN</div>
<div id="cyan" class="tab">CYAN</div>
</div>
<div class="contents">
<div id="red" class="content"></div>
<div id="blue" class="content"></div>
<div id="yellow" class="content"></div>
<div id="green" class="content"></div>
<div id="cyan" class="content"></div>
</div>
</div>
Thanks A lot Guys..

Related

How to rotate and scale cards while swiping

As I'm trying to make a carousel that rotates I wonder how to move the cards rotated and it scales from a minimum of 0.8(left and right cards) and a maximum scale of 1(center card) when the user keeps swiping
Scale:
left = 0.8
center = 1
right = 0.8
I'm trying to solve on how to rotate them using transform and z-index properties. The cards will also rotate however I'm still trying to make a formula on how to make a function that makes the cards rotate
Any alternative solutions are accepted The animation is
similar to this carousel from codepen however it doesn't swipe Carousel Rotate
const CONTAINER_FLEX = document.querySelector('.container-flex');
const items = document.querySelectorAll('.item');
let touchStartX = 0;
let touchMoveX = 0;
let count = 0;
let current_translate = 0;
let previous_translate = 0;
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchStartX = event.touches[0].pageX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
current_translate = previous_translate + (touchMoveX - touchStartX);
console.log(current_translate);
items[1].style.transform = `translateX(${current_translate}px)`;
});
CONTAINER_FLEX.addEventListener('touchend', () => {
current_translate = touchMoveX - touchStartX;
previous_translate = current_translate;
});
*,
::before,
::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 900px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
transform: translateX(100px);
z-index: 1;
}
.item-2 {
background-color: #3498db;
z-index: 2;
}
.item-3 {
background-color: #1abc9c;
transform: translateX(-100px);
z-index: 1;
}
<div class="main-container">
<div class="container-flex" id="container-flex">
<div class="item item-1">
<h1>1</h1>
</div>
<div class="item item-2">
<h1>2</h1>
</div>
<div class="item item-3">
<h1>3</h1>
</div>
</div>
</div>
Here is a working example https://jsfiddle.net/4ue5sgm9/3/
I wonder how to move the cards when it goes from 0 to 200 however
Have all your cards in an array.
var cards = [ thing1, thing2, thing3];
Use % - modulus operator, it's the secret for cycling back to the beginning
cardIndex = (cardIndex + 1) % cards.length
Copied from the chat. I made it verbose for clarity
scrollLeft() {
nextIndex = items.indexOf(displayed[2])
nextIndex = ++nextIndex % items.length-1
displayed = items[nextIndex]
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] );
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] )
}
P.S. Write and iterator for items array. An iterator stops after the last item. An iterator is why "for (x in thisArray)" works. BUT write the next() function to return "% this.length-1" instead => now you have a never-ending looper. All that code just above goes away.

Horizontal scroll areas with buttons and gradients

This is my code so far:
// Show and hide gradients
$(document).ready(function() {
$(".scroll-area").each(function(index) {
if ($(this)[0].scrollWidth <= $(this)[0].clientWidth) {
$(this).closest(".container").find(".left").css("display", "none");
$(this).closest(".container").find(".right").css("display", "none");
} else {
$(this).scroll(function() {
if ($(this)[0].scrollWidth > $(this)[0].clientWidth) {
if ($(this).scrollLeft() > 0) {
$(this).closest(".container").find(".left").css("display", "block");
}
if ($(this).scrollLeft() == 0) {
$(this).closest(".container").find(".left").css("display", "none");
}
var fullWidth = $(this)[0].scrollWidth - $(this)[0].offsetWidth - 1;
if ($(this).scrollLeft() >= fullWidth) {
$(this).closest(".container").find(".right").css("display", "none");
}
if ($(this).scrollLeft() < fullWidth) {
$(this).closest(".container").find(".right").css("display", "block");
}
}
});
}
});
});
// Scroll buttons
let interval;
$('.scroll-btn').on('mousedown', ({
target
}) => {
const type = $(target).attr('id');
interval = setInterval(() => {
var x = $('#a').scrollLeft();
$('#a').scrollLeft(type === 'left-arrow' ? x - 10 : x + 10);
}, 50);
});
$('.scroll-btn').on('mouseup', () => clearInterval(interval));
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
}
.container {
width: 550px;
height: 80px;
background-color: grey;
position: relative;
margin-bottom: 20px;
}
.scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
.left,
.right {
width: 50px;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
}
.left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
.right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
}
.arrow {
display: block;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 15px;
cursor: pointer;
}
.left-arrow {
left: 0;
}
.right-arrow {
right: 0;
}
.left-arrow div,
.right-arrow div {
font-size: 40px;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="container">
<div id="x" class="left"></div>
<div class="right"></div>
<div class="arrow left-arrow">
<div class="scroll-btn" id="left-arrow">
<</div>
</div>
<div class="arrow right-arrow">
<div class="scroll-btn" id="right-arrow">></div>
</div>
<div id="a" class="scroll-area">
<div class="text">Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one container. Lorem ipsum.</div>
</div>
</div>
The needs are:
The arrows should appear and disappear in the same way like the gradients.
If there is not enough text to cause a scrollable area, there should be no gradient and now arrow.
There should be more than one container in the end.
Can somebody help me to do that? I would be super thankful!
You can put your arrows inside the left/right gradient divs. That way they will show/hide same way as the gradients.
EDIT
I cleaned up the code a bit since the original answer was kinda messy. (or 'weird' as mstephen19 put it :)).
// Show gradient and left/right arrows only if scrollable
$(".scroll-area").each((i, el) => {
$(el).parent().find(".right")[el.scrollWidth > el.clientWidth ? "show" : "hide"]();
});
// Show/hide gradient and arrows on scroll
$('.scroll-area').scroll((e) => {
const fullWidth = $(e.target)[0].scrollWidth - $(e.target)[0].offsetWidth - 1;
const left = $(e.target).scrollLeft()
$(e.target).parent().find(".left, .left-arrow")[left > 0 ? "show" : "hide"]();
$(e.target).parent().find(".right, .right-arrow")[left < fullWidth ? "show" : "hide"]();
});
// Scroll on left/right arrow mouse down
let intervalId;
$(".left-arrow, .right-arrow").on("mousedown", (e) => {
const scroll = $(e.target).closest(".container").find(".scroll-area");
intervalId = setInterval(() => {
const left = scroll.scrollLeft();
scroll.scrollLeft(e.target.classList.contains("left-arrow") ? left - 10 : left + 10);
}, 50);
}).on("mouseup mouseleave", () => {
clearInterval(intervalId);
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
}
.container {
width: 550px;
height: 80px;
background-color: grey;
position: relative;
margin-bottom: 20px;
margin-left: 20px;
}
.scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
.left,
.right {
width: 50px;
height: 100%;
position: absolute;
top: 0;
}
.left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
.right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
text-align: right;
}
.left-arrow,
.right-arrow {
margin: 0 10px;
position: absolute;
top: 50%;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
cursor: pointer;
user-select: none;
font-size: 40px
}
.left-arrow {
display: none;
left: -25px;
}
.right-arrow {
right: -25px;
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="left-arrow"><</div>
<div class="right-arrow">></div>
<div class="scroll-area">
<div class="text">Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one container. Lorem ipsum.</div>
</div>
</div>
<div class="container">
<div class="left"><span class="left-arrow"><</span></div>
<div class="right"><span class="right-arrow">></span></div>
<div class="scroll-area">
<div class="text">No scroll.</div>
</div>
</div>
</body>
</html>
Some things about your code:
Your original code would not work with multiple containers, because you had a hardcoded #a ID in the interval code. You should really only have IDs on one element ideally, anyways (they're unique identifiers, while classes can be placed on multiple elements). The .scroll-area element should be found based on the target clicked.
You should combine your gradient and arrow elements into one element. By that, I mean making the div in which the arrow lives should be a child of the gradient div. Why manage them both separately?
Use class adding/removing/toggling instead of directly setting the CSS. Remember - when you find yourself writing the same code multiple times, it usually means there is a way to condense it down and make your code more dry and easier to understand + read.
Don't use the literal < and > symbols, as it can confuse some browsers. Use < and > instead.
Rather than toggling display to none and block, it's better to use visibility in this specific case. In my example, we use opacity for a fun fading effect.
Don't forget to listen for both mouseup mouseout events :)
Here is the working solution. I've refactored the code a bit:
let interval;
$('.arrow').on('mousedown', ({ target }) => {
const type = target.classList[1];
const scrollArea = $(target).parent().find('.scroll-area');
interval = setInterval(() => {
const prev = scrollArea.scrollLeft();
scrollArea.scrollLeft(type === 'left-arrow' ? prev - 10 : prev + 10);
}, 50);
});
$('.arrow').on('mouseup mouseout', () => clearInterval(interval));
$('.scroll-area').on('scroll', ({ target }) => {
const left = $(target).parent().find('.left-arrow');
const right = $(target).parent().find('.right-arrow');
const scroll = $(target).scrollLeft();
const fullWidth = $(target)[0].scrollWidth - $(target)[0].offsetWidth;
if (scroll === 0) left.addClass('hide');
else left.removeClass('hide');
if (scroll > fullWidth) right.addClass('hide');
else right.removeClass('hide');
});
.container {
width: 550px;
height: 80px;
background: grey;
position: relative;
}
.right-arrow,
.left-arrow {
height: 100%;
width: 50px;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
cursor: pointer;
transition: all 0.2s linear;
}
.scroll-area {
white-space: nowrap;
overflow-x: scroll;
height: 100%;
}
.right-arrow {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 500px;
}
.left-arrow {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0px;
}
.scroll-btn {
pointer-events: none;
}
.hide {
opacity: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="container">
<div class="arrow left-arrow">
<div class="scroll-btn" id="left-arrow"><</div>
</div>
<div class="arrow right-arrow">
<div class="scroll-btn" id="right-arrow">></div>
</div>
<div class="scroll-area">
<div class="text">
Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one
container. Lorem ipsum.
</div>
</div>
</div>
PS: If you don't like the fade effect, remove the transition: all 0.2s linear; part of the CSS, and switch .hide's opacity: 0 to visibility: hidden.

Navbar disappears after scrollIntoView() use on mobile view

Problem: NavBar disappears after scrollIntoView() used on mobile view.
Related JS
function disableScroll() {
window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}
function enableScroll() {
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
window.removeEventListener('touchmove', preventDefault, wheelOpt);
window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}
function scroll_to_chapters() {
const chapters = document.getElementsByClassName("chapter_list")[0];
if (nav.classList.contains("nav-active")) {
navLinks.forEach((link) => {
if (link.style.animation) {
link.style.animation = '';
}
});
enableScroll();
burger.classList.toggle('toggle');
nav.classList.toggle('nav-active');
}
chapters.scrollIntoView({ block: 'start', behavior: 'smooth' })
}
const navSlide = ()=> {
burger.addEventListener('click', ()=> {
//Toggle NavBar
nav.classList.toggle('nav-active');
//Animate Links
navLinks.forEach((link, index)=> {
if (link.style.animation) {
enableScroll();
link.style.animation = '';
}
else {
disableScroll();
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7 + 0.5}s`;
}
});
burger.classList.toggle('toggle');
});
}
I'm not quite sure but there might be a problem with the disabling and enabling scrolling. I didn't want mobile users to be able to scroll while the navbar menus are opened.
Navbar HTML
<div class="wrapper">
<div class="fix">
<header>
<div class="container">
<nav>
<img src="{% static 'img/northernlogo.png' %}" class="logo" alt="logo">
<ul class="nav-links">
<li>Home</li>
<li>Chapters</li>
<li>About</li>
<li>Links</li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
</div>
</header>
</div>
</div>
Related CSS
.container {
width: 100%;
margin: 0 0;
}
.container::after {
content: '';
display: grid;
clear: both;
}
.burger {
display: none;
margin-top: 20px;
cursor: pointer;
}
.burger div {
width: 25px;
height: 3px;
background: #EEEEEE;
margin: 5px;
transition: all 0.3s ease;
}
#media only screen and (max-width: 800px) {
.wrapper {
overflow: hidden;
position: relative;
}
.nav-links {
-webkit-box-shadow: inset 0 0.5em 1.5em -0.5em black;
position: absolute;
right: 0;
height: 100%;
top: 70px;
background-color: #3a345c;
z-index: 99;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.nav-links li {
opacity: 0;
padding-bottom: 50px;
padding-top: 50px;
}
.nav-links li a {
font-size: 20px;
font-weight: bold;
}
.burger {
display: block;
}
}
Picture of the Error
Before
After
How to Reproduce
Open the website on mobile view. Open the navbar from the home menu and click chapters. It'll take you to the chapters but now the navbar is gone.
Editor's note:
The accepted answer features a self-contained reproducible example.
This happens because .nav-links are position: absolute with:
a position: static (by default) parent .fix, and
a position: relative grandparent .wrapper.
In this case, scrollIntoView({block: 'start', ...}) scrolls .fix out of view of .wrapper before scrolling .wrapper itself.
{block: 'center', ...} does the same.
{block: 'end', ...} and {block: 'nearest', ...} don't.
You can't scroll .fix back into view because .wrapper has overflow: hidden.
Solution
Make .fix have position: relative and make .nav-links have height: 100vh.
.fix {
position: relative;
}
.nav-links {
height: 100vh;
}
Run this code snippet to reproduce the problem, and click on the toggle to try with answer:
const burger = document.querySelector('.burger');
const nav = document.querySelector('.nav-links');
const navLinks = document.querySelectorAll('.nav-links li');
// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {
37: 1,
38: 1,
39: 1,
40: 1
};
function preventDefault(e) {
e.preventDefault();
}
function preventDefaultForScrollKeys(e) {
if (keys[e.keyCode]) {
preventDefault(e);
return false;
}
}
// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
}));
} catch (e) {}
var wheelOpt = supportsPassive ? {
passive: false
} : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';
// call this to Disable
function disableScroll() {
window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}
// call this to Enable
function enableScroll() {
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
window.removeEventListener('touchmove', preventDefault, wheelOpt);
window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}
function read_more_less(button) {
var x = $('#more');
$(button).find('i').remove();
if ($(button).text().trim() === 'Read more') {
$(button).html($('<i/>', {
class: 'fas fa-sort-down'
})).append(' Read less');
x.fadeIn();
} else {
$(button).html($('<i/>', {
class: 'fas fa-sort-up'
})).append(' Read more');
x.fadeOut();
}
}
function scroll_to_chapters() {
const chapters = document.getElementsByClassName("chapter_list")[0];
if (nav.classList.contains("nav-active")) {
navLinks.forEach((link) => {
if (link.style.animation) {
link.style.animation = '';
}
});
enableScroll();
burger.classList.toggle('toggle');
nav.classList.toggle('nav-active');
}
chapters.scrollIntoView({
block: 'start',
behavior: 'smooth'
})
}
const navSlide = () => {
burger.addEventListener('click', () => {
//Toggle NavBar
nav.classList.toggle('nav-active');
//Animate Links
navLinks.forEach((link, index) => {
if (link.style.animation) {
enableScroll();
link.style.animation = '';
} else {
disableScroll();
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7 + 0.5}s`;
}
});
burger.classList.toggle('toggle');
});
}
navSlide();
function toggleAnswer(button) {
var wrapper = document.querySelector('.wrapper');
wrapper.classList.toggle('answer');
button.innerHTML = wrapper.classList.contains('answer') ? 'Click to try without answer' : 'Click to try with answer';
}
body {
margin: 0;
background: #212121;
font-family: 'Glory', serif !important;
}
.container {
width: 100%;
margin: 0 0;
}
.container::after {
content: '';
display: grid;
clear: both;
}
.burger {
display: none;
margin-top: 20px;
cursor: pointer;
}
.burger div {
width: 25px;
height: 3px;
background: #EEEEEE;
margin: 5px;
transition: all 0.3s ease;
}
header {
background: #3a345c;
}
nav {
justify-content: space-around;
display: flex;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav a:not([data-attr="img"]) {
color: #eeeeee;
text-decoration: none;
text-transform: uppercase;
font-size: 15px;
}
#media only screen and (max-width: 800px) {
.wrapper {
overflow: hidden;
position: relative;
}
.nav-links {
-webkit-box-shadow: inset 0 0.5em 1.5em -0.5em black;
position: absolute;
right: 0;
height: 100%;
top: 70px;
background-color: #3a345c;
z-index: 99;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.nav-links li {
opacity: 0;
padding-bottom: 50px;
padding-top: 50px;
}
.nav-links li a {
font-size: 20px;
font-weight: bold;
}
.burger {
display: block;
}
}
.nav-active {
transform: translateX(0%);
}
#keyframes navLinkFade {
from {
opacity: 0;
transform: translateX(50px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* Work within Stack Snippets window height */
.nav-links li {
padding: 10px;
}
/* Answer */
.answer .fix {
position: relative;
}
.answer .nav-links {
height: 100vh;
}
<html>
<head>
</head>
<body>
<div class="wrapper">
<div class="fix">
<header>
<div class="container">
<nav>
<a style="height: 70px;"></a>
<ul class="nav-links">
<li>Home</li>
<li>Chapters</li>
<li>About</li>
<li>Links</li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
</div>
</header>
</div>
<button onclick="toggleAnswer(this);">Click to try with answer</button>
<div style="height: 500px;">
</div>
<div class="chapter_list">
<h2 style="color: white; padding-left: 10px;">Chapter list</h2>
</div>
</div>
</body>
</html>
I do not know what is wrong with scrollIntoView, but I remark that when I move the chapiters parts to be a direct child of body, that problem disapear.
However, there is a way to do that same behavior without any js code:
In your CSS code, add scroll-behavior: smooth; to the root.
Add an id to the chapiter : <div id="chap_id" class="chapter_list">
Turn the href attribut of chapiter link in to : an page#id link : <a href="page_chapters#chap_id">
You can find a doc on scroll-behavior here.
So you are using the body as overscroll and there is also a wrapper with the same height (and it's basically the same as the body) with an overscroll hidden.
Your menu you let slide in has a 100% height, so the bottom is at nav:height + 100%. I assume the scroll into view first scrolls the wrapper (as it overflows the nav:height) and then it scrolls the body. Making the nav-bar disappear, as the overflow is hidden.
You can fix this by adjusting the menu height to make it actually 100% in height: e.g. CSS: calc(100% - 70px) or using flex-box and let the menu flex:1.
You have to fix you navbar using "position: fixed" property. Add & Modify given CSS
Here is the result
#media only screen and (max-width: 800px) {
/*ADD This*/
.fix {
position: fixed;
width: 100%;
z-index: 1;
}
/*modify this*/
.nav-links {
height: 100vh;
}
.content {
margin-top: 90px;
}
}

Clicking card in memory game doesn't flip it over

I'm trying to make a memory game and am struggling to get the cards to flip over when they're clicked. I expected the following for loop to call the function displayCard when a card (corresponding to each li item with class card) is clicked, which function toggles the classes show and open (sets the card to visible [displays icon] and changes the background color). Any suggestions?
CodePen
For loop:
for (let i = 0; i < cards.length; i++) {
card = cards[i];
card.addEventListener('click', displayCard);
card.addEventListener('click', cardOpen);
card.addEventListener('click', congratulations);
}
displayCard function:
let displayCard = function() {
this.classList.toggle('open');
this.classList.toggle('show');
this.classList.toggle('disabled');
};
CSS for classes show and open:
.card-deck .card.open {
/* transform: rotateY(0); */
background: #02b3e4;
cursor: default;
animation-name: flipInY;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.show {
font-size: 33px;
}
.show {
visibility: visible !important;
opacity: 100 !important;
}
There are two errors in your code that need to be fixed and then the flipping occurs :
in the startGame function, deck.appendChild is not a function. deck was initialized with document.getElementsByClassName('card-deck'). And document.getElementsByClassName returns an array. You need to select the first index of this array.
in the startGame function, interval is not defined. Your function is called before the interval variable is declared. Either move up the interval variable declaration of declare it with the var keyword to "reserve" the identifier.
let card = document.getElementsByClassName('card');
// Spread operator (new in ES6) allows iterable to expand where 0+ arguments are expected
let cards = [...card];
let deck = document.getElementsByClassName('card-deck')[0];
let moves = 0;
let counter = document.querySelector('.moves');
let stars = document.querySelectorAll('.fa-star');
let matchingCard = document.getElementsByClassName('matching');
let starsList = document.querySelectorAll('.stars li');
let closeIcon = document.querySelector('.close');
let modal = document.getElementsByClassName('main-modal');
let openedCards = [];
// Game timer
let second = 0, minute = 0, hour = 0;
let timer = document.querySelector('.timer');
let interval;
// Shuffle function from http://stackoverflow.com/a/2450976
function shuffle(array) {
let currentIndex = array.length, temporaryValue, randomIndex;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// Shuffles cards upon page load
document.body.onload = startGame();
function startGame() {
// Shuffles deck
cards = shuffle(cards);
// Removes any existing classes from each card
for (let i = 0; i < cards.length; i++) {
deck.innerHTML = '';
[].forEach.call(cards, function(item) {
deck.appendChild(item);
});
cards[i].classList.remove('show', 'open', 'matching', 'disabled');
}
// Resets number of moves
moves = 0;
counter.innerHTML = moves;
// Resets star rating
for (let i = 0; i < stars.length; i++) {
stars[i].style.color = '#ffd700';
stars[i].style.visibility = 'visible';
}
// Resets timer
let second = 0;
let minute = 0;
let hour = 0;
let timer = document.querySelector('.timer');
timer.innerHTML = '0 mins 0 secs';
if (typeof interval != "undefined") {
sclearInterval(interval);
}
}
// Toggles open and show classes to display cards
let displayCard = function() {
this.classList.toggle('open');
this.classList.toggle('show');
this.classList.toggle('disabled');
};
// Adds opened cards to openedCards list and checks if cards are a match or not
function cardOpen() {
openedCards.push(this);
let len = openedCards.length;
if (len === 2) {
moveCounter();
if (openedCards[0].type === openedCards[1].type) {
matching();
} else {
notMatching();
}
}
}
// When cards match
function matching() {
openedCards[0].classList.add('matching', 'disabled');
openedCards[1].classList.add('matching', 'disabled');
openedCards[0].classList.remove('show', 'open');
openedCards[1].classList.remove('show', 'open');
openedCards = [];
}
// When cards don't match
function notMatching() {
openedCards[0].classList.add('not-matching');
openedCards[1].classList.add('not-matching');
disable();
setTimeout(function() {
openedCards[0].classList.remove('show', 'open', 'not-matching');
openedCards[1].classList.remove('show', 'open', 'not-matching');
enable();
openedCards = [];
}, 1100);
}
// Disables cards temporarily
function disable() {
Array.prototype.filter.call(cards, function(card) {
card.classList.add('disabled');
});
}
// Enables cards, disables matching cards
function enable() {
Array.prototype.filter.call(cards, function(card) {
card.classList.remove('disabled');
for (let i = 0; i < matchingCard.length; i++) {
matchingCard[i].classList.add('disabled');
}
});
}
// Counts player's moves
function moveCounter() {
moves++;
counter.innerHTML = moves;
// Starts timer on first click
if (moves == 1) {
second = 0;
minute = 0;
hour = 0;
startTimer();
}
// Sets star rating based on number of moves
if (moves > 8 && moves < 12) {
for (i = 0; i < 3; i++) {
if (i > 1) {
stars[i].style.visibility = 'collapse';
}
}
}
else if (moves > 13) {
for (i = 0; i < 3; i++) {
if (i > 0) {
stars[i].style.visibility = 'collapse';
}
}
}
}
function startTimer() {
interval = setInterval(function() {
timer.innerHTML = minute + 'mins ' + second + 'secs';
second++;
if (second == 60) {
minute++;
second = 0;
}
if (minute == 60) {
hour++;
minute = 0;
}
}, 1000);
}
// Congratulates player when all cards match and shows modal, moves, time and rating
function congratulations() {
if (matchingCard.length == 16) {
clearInterval(interval);
let finalTime = timer.innerHTML;
// Shows congratulations modal
modal.classList.add('show');
let starRating = document.querySelector('.stars').innerHTML;
// Shows move, time, and rating on modal
document.getElementsByClassName('final-move').innerHTML = moves;
document.getElementsByClassName('star-rating').innerHTML = starRating;
document.getElementsByClassName('total-time').innerHTML = finalTime;
closeModal();
}
}
// Closes modal upon clicking its close icon
function closeModal() {
closeIcon.addEventListener('click', function(e) {
modal.classList.remove('show');
startGame();
});
}
function reset() {
modal.classList.remove('show');
startGame();
}
// Adds event listeners to each card
for (let i = 0; i < cards.length; i++) {
card = cards[i];
card.addEventListener('click', displayCard);
card.addEventListener('click', cardOpen);
card.addEventListener('click', congratulations);
}
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #ffffff;
font-family: 'Permanent Marker', cursive;
font-size: 16px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
h1 {
font-family: 'Gloria Hallelujah', cursive;
}
/* DECK OF CARDS */
.card-deck {
width: 85%;
background: #716F71;
padding: 1rem;
border-radius: 4px;
box-shadow: 8px 9px 26px 0 rgba(46, 61, 73, 0.5);
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
margin: 0 0 3em;
}
.card-deck .card {
height: 3.7rem;
width: 3.7rem;
margin: 0.2rem 0.2rem;
background: #141214;;
font-size: 0;
color: #ffffff;
border-radius: 5px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 5px 2px 20px 0 rgba(46, 61, 73, 0.5);
}
.card-deck .card.open {
/* transform: rotateY(0); */
background: #02b3e4;
cursor: default;
animation-name: flipInY;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.show {
font-size: 33px;
}
.show {
visibility: visible !important;
opacity: 100 !important;
}
.card-deck .card.matching {
cursor: default;
background: #E5F720;
font-size: 33px;
animation-name: rubberBand;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
}
.card-deck .card.not-matching {
animation-name: pulse;
-webkit-backface-visibility: visible !important;
backface-visibility: visible !important;
animation-duration: .75s;
background: #e2043b;
}
.card-deck .card.disabled {
pointer-events: none;
opacity: 0.9;
}
/* SCORE PANEL */
.score-panel {
text-align: left;
margin-bottom: 10px;
}
.score-panel .stars {
margin: 0;
padding: 0;
display: inline-block;
margin: 0 5px 0 0;
}
.score-panel .stars li {
list-style: none;
display: inline-block;
}
.score-panel .restart {
float: right;
cursor: pointer;
}
.fa-star {
color: #FFD700;
}
.timer {
display: inline-block;
margin: 0 1rem;
}
/* CONGRATULATIONS MODAL */
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
margin: 70px auto;
padding: 20px;
background: #ffffff;
border-radius: 5px;
width: 85%;
position: relative;
transition: all 5s ease-in-out;
font-family: 'Gloria Hallelujah', cursive;
}
.popup h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup .close:hover {
color: #e5f720;
}
.popup .congrats-message,
.info-message {
max-height: 30%;
overflow: auto;
text-align: center;
}
.star-rating li {
display: inline-block;
}
.play-again {
background-color: #141214;
padding: 0.7rem 1rem;
font-size: 1.1rem;
display: block;
margin: 0 auto;
width: 50%;
font-family: 'Gloria Hallelujah', cursive;
color: #ffffff;
border-radius: 5px;
}
/* Animations */
#keyframes flipInY {
from {
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
animation-timing-function: ease-in;
opacity: 0;
}
40% {
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
animation-timing-function: ease-in;
}
60% {
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
opacity: 1;
}
80% {
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
}
to {
transform: perspective(400px);
}
}
#keyframes rubberBand {
from {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1);
}
40% {
transform: scale3d(0.75, 1.25, 1);
}
50% {
transform: scale3d(1.15, 0.85, 1);
}
65% {
transform: scale3d(.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, .95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
#keyframes pulse {
from {
transform: scale3d(1, 1, 1);
}
50% {
transform: scale3d(1.2, 1.2, 1.2);
}
to {
transform: scale3d(1, 1, 1);
}
}
/* MEDIA QUERIES */
#media (max-width: 320px) {
.card-deck {
width: 85%;
}
.card-deck .card {
height: 4.7rem;
width: 4.7rem;
}
}
/* For tablets and larger screens */
#media (min-width: 768px) {
.container {
font-size: 22px;
}
.card-deck {
width: 660px;
height: 680px;
}
.card-deck .card {
height: 125px;
width: 125px;
}
.popup {
width: 60%;
}
}
<!-- <!doctype html> -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Matching Game</title>
<meta name="description" content="">
<link rel="stylesheet prefetch" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<link rel="stylesheet prefetch" href="https://fonts.googleapis.com/css?family=Coda">
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<header>
<h1>Matching Game</h1>
</header>
<section class="score-panel">
<ul class="stars">
<li><i class="fa fa-star"></i></li>
<li><i class="fa fa-star"></i></li>
<li><i class="fa fa-star"></i></li>
</ul>
<span class="moves">0</span> moves
<div class="timer"></div>
<div class="restart" onclick=startGame()>
<i class="fa fa-repeat"></i>
</div>
</section>
<ul class="card-deck">
<li class="card" type="diamond">
<i class="fa fa-diamond"></i>
</li>
<li class="card" type="plane">
<i class="fa fa-paper-plane-o"></i>
</li>
<li class="card matching" type="anchor">
<i class="fa fa-anchor"></i>
</li>
<li class="card" type="bolt" >
<i class="fa fa-bolt"></i>
</li>
<li class="card" type="cube">
<i class="fa fa-cube"></i>
</li>
<li class="card matching" type="anchor">
<i class="fa fa-anchor"></i>
</li>
<li class="card" type="leaf">
<i class="fa fa-leaf"></i>
</li>
<li class="card" type="bicycle">
<i class="fa fa-bicycle"></i>
</li>
<li class="card" type="diamond">
<i class="fa fa-diamond"></i>
</li>
<li class="card" type="bomb">
<i class="fa fa-bomb"></i>
</li>
<li class="card" type="leaf">
<i class="fa fa-leaf"></i>
</li>
<li class="card" type="bomb">
<i class="fa fa-bomb"></i>
</li>
<li class="card open show" type="bolt">
<i class="fa fa-bolt"></i>
</li>
<li class="card" type="bicycle">
<i class="fa fa-bicycle"></i>
</li>
<li class="card" type="plane">
<i class="fa fa-paper-plane-o"></i>
</li>
<li class="card" type="cube">
<i class="fa fa-cube"></i>
</li>
</ul>
<div class="main-modal overlay">
<div class="popup">
<h2>Congratulations!</h2>
<a class="close" href=# >×</a>
<div class="congrats-message">
Congratulations, you're a winner!
</div>
<div class="info-message">
<p>You made <span class=final-move></span> moves </p>
<p>In <span class=total-time></span></p>
<p>Rating: <span class=star-rating></span></p>
</div>
<button class="play-again" onclick="reset()">
Play again
</button>
</div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>

Using jQuery to reorder a list of items as my CSS method not 100%

I have been trying endlessly to re-order position of items for mobile using CSS but simple does not seem to be cutting the mustard... its working of course but for some reason on 10 items 2 does position right so want to go down the JS road however not really done much JS and hoping someone could lend me a hand.
Basically on desktop on display a list of items side by side, for example
1[L] - 2[L]
3[R] - 4[R]
5[L] - 6[L]
7[R] - 8[R]
9[L] - 10[L]
Each item has a background image showing 2 sections, above i added [L] and [R] to show Left and Right as the backgrounds would show item logo in the same position on that one line however on mobile i need to somehow alternate the position because would be a slight different sequence as 1 per line on full width.
1[L]
3[R]
2[L]
4[R]
5[L]
7[R]
6[L]
8[R]
9[L]
10[L]
of course with an odd amount would work out ok.... or am i wrong in this theory?
Actually writing that out would explain why im getting the issue as the last 2 are left, left so no right to go above it... so doing with JS would have the same result i guess?
example: 15 items (works fine) https://jsfiddle.net/vgrd7oww/13/
example: 10 items (your see 2 items same half way through) https://jsfiddle.net/vgrd7oww/14/
Anyone know of any solution for this? either with my current CSS or some JS?
CSS:
.collection-hover-container {
display: flex;
flex-direction: column;
ul.collection-list {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
list-style: none;
padding: 0;
margin: 0;
overflow: hidden;
.collection-list-item {
display: flex;
width: calc(49%);
margin-left: 2%;
box-sizing: border-box;
&.collection-hover {
margin-bottom: 10px !important;
position: relative;
&:nth-child(4n+1) div:first-child,
&:nth-child(4n+2) div:first-child {
order: 1;
right: 0;
}
&:nth-child(4n+3) div:last-child,
&:nth-child(4n+4) div:last-child {
right: 0;
}
div:first-child {
width: 66.66%;
}
div:last-child {
width: 33.33%;
}
.collection-list-hover-desc {
display: none;
position: absolute;
bottom: 0;
background-color: rgba(51, 51, 51, 0.4);
p {
padding: 10px;
color: #ffffff;
font-size: 0.7em;
}
}
.collection-list-hover-button {
width: 32.2%;
display: block;
position: absolute;
bottom: 10px;
text-align: center;
.button {
font-size: 0.8em;
border: 2px solid #fff;
color: #fff;
text-transform: uppercase;
background: #f14fa1;
white-space: nowrap;
padding: 7px 13px 5px 13px;
border-radius: 3px;
}
}
a {
display: inline-block;
background-size: cover;
animation: fadeout 1.8s, bp-change 0.1s;
-moz-animation: fadeout 1.8s, bp-change 0.1s;
/* Firefox */
-webkit-animation: fadeout 1.8s, bp-change 0.1s;
/* Safari and Chrome */
-o-animation: fadeout 1.8s, bp-change 0.1s;
background-position: 0 0;
width: 100%;
&:hover {
animation: fadein 1.8s, bp-change 0.1s;
-moz-animation: fadein 1.8s, bp-change 0.1s;
/* Firefox */
-webkit-animation: fadein 1.8s, bp-change 0.1s;
/* Safari and Chrome */
-o-animation: fadein 1.8s, bp-change 0.1s;
background-position: -50% 99%;
}
}
}
}
}
}
#-webkit-keyframes fadein {
from {
opacity:0.7;
}
to {
opacity:1;
}
}
#-webkit-keyframes fadeout {
from {
opacity:0.7;
}
to {
opacity:1;
}
}
#-webkit-keyframes bp-change {
from {
background-position:0 0;
}
to {
background-position:-50% 100%;
}
}
/* Tablet */
#media only screen and (max-width: 959px) {
.collection-list {
.collection-list-item {
.collection-list-hover-button {
.button {
font-size: 0.6rem;
border: 1px solid #fff;
padding: 5px 8px;
}
}
}
}
}
#media only screen and (max-width: 767px) {
.collection-hover-container {
ul.collection-list {
.collection-list-item {
width: calc(100% - 10px) !important;
&.collection-hover {
margin-left: 0 !important;
&:nth-child(4n+1) div:first-child,
&:nth-child(4n+2) div:first-child {
order: 0;
}
&:nth-child(odd) div:first-child {
order: 1;
}
&:nth-child(even) {
order: 1;
}
.collection-list-hover-desc {
p {
padding: 5px 10px;
font-size: 1em;
}
}
.collection-list-hover-button {
.button {
font-size: 0.6em;
padding: 5px 10px;
}
}
}
}
}
}
.featured-collections {
.collection-list {
display: block;
}
}
}
I simplified your example by using a string for the images ("1-L", "2-L", etc). I think it will make the answer easier to understand. The code below is to show how something like that could be done with JQuery.
Instead of a list, I think it's easier if we use div.
The CSS:
#wrapper div.item {display:inline;}
The JQuery code:
$(document).ready(function(){
var mobile = true; // your mobile flag
var arrayImages = [ "1-L", "2-L", "3-R", "4-R",
"5-L", "6-L", "7-R", "8-R",
"9-R", "10-R"]; // your images. Arrays start with index 0.
var totalImages = arrayImages.length; // total number of images
// if it's not mobile, then add a line break after the second image
if (mobile == false){
var theHtml = "";
for (let i = 0; i< totalImages;i++){
var theImageHtml = '<div class="item item-1">' + arrayImages[i] + '</div>';
// if it's an odd number image (the array starts at 0) add a line break at the end
if (i%2==1){
theHtml += theImageHtml + '<br/>';
}
else {
theHtml += theImageHtml + '</div>';
}
$('#wrapper').html(theHtml);
}
};
// if it's mobile, take up to 4 images and display them in this order: 1, 3, 2, 4.
if (mobile == true){
var theHtml = "";
for (let i = 0; i< totalImages;i++){
var theImageHtml1 = "";
var theImageHtml2 = "";
var theImageHtml3 = "";
var theImageHtml4 = "";
var theImageHtml1 = '<div class="item item-1">' + arrayImages[i] + '</div><br/>';
if (i+1 < totalImages){
i++;
var theImageHtml2 = '<div class="item item-1">' + arrayImages[i] + '</div><br/>';
}
if (i+1 < totalImages){
i++;
var theImageHtml3 = '<div class="item item-1">' + arrayImages[i] + '</div><br/>';
}
if (i+1 < totalImages){
i++;
var theImageHtml4 = '<div class="item item-1">' + arrayImages[i] + '</div><br/>';
}
theHtml += theImageHtml1 + theImageHtml3 + theImageHtml2 + theImageHtml4;
}
$('#wrapper').html(theHtml);
}
});
The HTML:
<div id="wrapper"></div>
Remember to include jQuery library inside the head tag:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
</head>

Categories

Resources