Complex continuous scroll loop - javascript

I have a code similar to:
<div id='right-column'>
<div id='results'>
<div id='result1>
<div class='main'></div>
<div class='details'></div>
</div>
<!-- ... -->
<div id='result50>
<div class='main'></div>
<div class='details'></div>
</div>
</div>
</div>
the total number of results depends of the ajax query, I insert all the results dynamically in one go.
div.main is always visible (fixed height) and div.details "unfolds/folds" below div.main when the user clicks on a result div.
the details div height can vary.
If #results scrollHeight is bigger than #right-column height, I would like to create a continuous scroll loop.
In this case, scrolling past #result50 would show #result1, scrolling before #result1 would show #result50.
I can't .append() the first child to the bottom as in some cases a portion of a result can be seen on top and at the bottom of the column.
I can't duplicate a result unless I detect if .details is unfolded/folded.
The fact that the height of a result can change when a user unfolds the .details div, makes it even more complicated...
Here is an example of continuous scroll loop (2 columns):
$(document).ready(function() {
var num_children = $('#up-left').children().length;
var child_height = $('#up-left').height() / num_children;
var half_way = num_children * child_height / 2;
$(window).scrollTop(half_way);
function crisscross() {
$('#up-left').css('bottom', '-' + window.scrollY + 'px');
$('#down-right').css('bottom', '-' + window.scrollY + 'px');
var firstLeft = $('#up-left').children().first();
var lastLeft = $('#up-left').children().last();
var lastRight = $('#down-right').children().last();
var firstRight = $('#down-right').children().first();
if (window.scrollY > half_way ) {
$(window).scrollTop(half_way - child_height);
lastRight.appendTo('#up-left');
firstLeft.prependTo('#down-right');
} else if (window.scrollY < half_way - child_height) {
$(window).scrollTop(half_way);
lastLeft.appendTo('#down-right');
firstRight.prependTo('#up-left');
}
}
$(window).scroll(crisscross);
});
div#content {
width: 100%;
height: 100%;
position: absolute;
top:0;
right:0;
bottom:0;
left:0;
}
#box {
position: relative;
vertical-align:top;
width: 100%;
height: 200px;
margin: 0;
padding: 0;
}
#up-left {
position:absolute;
z-index:4px;
left: 0;
top: 0px;
width: 50%;
margin: 0;
padding: 0;
}
#down-right {
position:fixed;
bottom: 0px;
z-index: 5px;
left: 50%;
width: 50%;
margin: 0;
padding: 0;
}
h1 {margin: 0;padding: 0;color:#fff}
.black {background: black;}
.white {background: grey;}
.green {background: green;}
.brown {background: brown;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div id="content">
<div id="up-left">
<div id="box" class="brown">
<h1>ONE</h1>
</div>
<div id="box" class="black">
<h1>TWO</h1>
</div>
<div id="box" class="white">
<h1>THREE</h1>
</div>
<div id="box" class="black">
<h1>FOUR</h1>
</div>
<div id="box" class="white">
<h1>FIVE</h1>
</div>
<div id="box" class="black">
<h1>SIX</h1>
</div>
</div><!-- #up-left -->
<div id="down-right">
<div id="box" class="white">
<h1>SIX</h1>
</div>
<div id="box" class="black">
<h1>FIVE</h1>
</div>
<div id="box" class="white">
<h1>FOUR</h1>
</div>
<div id="box" class="black">
<h1>THREE</h1>
</div>
<div id="box" class="white">
<h1>TWO</h1>
</div>
<div id="box" class="green">
<h1>ONE</h1>
</div>
</div><!-- #down-right -->
</div><!-- .content -->
(fiddle: http://jsfiddle.net/franckl/wszg1d6c/)
Any hint/ideas on how I could do it ?

Move items to top or bottom based on scroll direction
You can use jQuery's .append() and .prepend() to move items without cloning them.
You'll use similar techniques to infinite scrolling with lazy loading (AJAX), but in this scenario you want to handle scrolling up as well as down, and instead of loading new content from the server, you're just recycling existing DOM elements in the list.
Below I demonstrate one technique. I store the scroll position in the element's .data cache for easy retrieval when detecting scrolling direction. I chose to detect scrolling direction to avoid making unnecessary variable assignments upfront to improve performance. Otherwise, you'd be getting elements and doing math for a scroll event that isn't going to happen in that direction.
The scroll handler:
$('#right-column').on('scroll', function (e) {
var $this = $(this),
$results = $("#results"),
scrollPosition = $this.scrollTop();
if (scrollPosition > ($this.data('scroll-position') || 0)) {
// Scrolling down
var threshold = $results.height() - $this.height() - $('.result:last-child').height();
if (scrollPosition > threshold) {
var $firstResult = $('.result:first-child');
$results.append($firstResult);
scrollPosition -= $firstResult.height();
$this.scrollTop(scrollPosition);
}
} else {
// Scrolling up
var threshold = $('.result:first-child').height();
if (scrollPosition < threshold) {
var $lastResult = $('.result:last-child');
$results.prepend($lastResult);
scrollPosition += $lastResult.height();
$this.scrollTop(scrollPosition);
}
}
$this.data('scroll-position', scrollPosition)
});
A complete working example:
$('#right-column').on('scroll', function (e) {
var $this = $(this),
$results = $("#results"),
scrollPosition = $this.scrollTop();
if (scrollPosition > ($this.data('scroll-position') || 0)) {
// Scrolling down
var threshold = $results.height() - $this.height() - $('.result:last-child').height();
if (scrollPosition > threshold) {
var $firstResult = $('.result:first-child');
$results.append($firstResult);
scrollPosition -= $firstResult.height();
$this.scrollTop(scrollPosition);
}
} else {
// Scrolling up
var threshold = $('.result:first-child').height();
if (scrollPosition < threshold) {
var $lastResult = $('.result:last-child');
$results.prepend($lastResult);
scrollPosition += $lastResult.height();
$this.scrollTop(scrollPosition);
}
}
$this.data('scroll-position', scrollPosition)
});
$('#results').on('click', '.result', function (e) {
$(this).find('.details').toggle();
});
$('#newNumber').on('input', function (e) {
var results = '';
for (var n = 1; n <= $(this).val(); n++) {
results +=
'<div class="result" id="result' + n + '">' +
' <div class="main">Result ' + n + '</div>' +
' <div class="details">Details for result ' + n + '</div>' +
'</div>';
}
$('#results').html(results);
});
body {
font-family: sans-serif;
}
h1 {
font: bold 2rem/1 Georgia, serif;
}
p {
line-height: 1.5;
margin-bottom: 1em;
}
label {
font-weight: bold;
margin-bottom: 1em;
}
.column {
box-sizing: border-box;
float: left;
width: 50%;
height: 100vh;
padding: 1em;
overflow: auto;
}
#right-column {
background-color: LemonChiffon;
}
.result {
padding: 1em;
cursor: pointer;
}
.result .main {
height: 2em;
font-weight: bold;
line-height: 2;
}
.result .details {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class=
"column" id="left-column">
<p>Existing DOM elements are moved to the top or bottom of the list depending on your scroll direction.</p>
<label>Change the number of results to display
<input id="newNumber" type="number" value="10" />
</div>
<div class=
"column" id="right-column">
<div id="results">
<div id="result1" class="result">
<div class="main">Result 1</div>
<div class="details">Details for result 1</div>
</div>
<div id="result2" class="result">
<div class="main">Result 2</div>
<div class="details">Details for result 2</div>
</div>
<div id="result3" class="result">
<div class="main">Result 3</div>
<div class="details">Details for result 3</div>
</div>
<div id="result4" class="result">
<div class="main">Result 4</div>
<div class="details">Details for result 4</div>
</div>
<div id="result5" class="result">
<div class="main">Result 5</div>
<div class="details">Details for result 5</div>
</div>
<div id="result6" class="result">
<div class="main">Result 6</div>
<div class="details">Details for result 6</div>
</div>
<div id="result7" class="result">
<div class="main">Result 7</div>
<div class="details">Details for result 7</div>
</div>
<div id="result8" class="result">
<div class="main">Result 8</div>
<div class="details">Details for result 8</div>
</div>
<div id="result9" class="result">
<div class="main">Result 9</div>
<div class="details">Details for result 9</div>
</div>
<div id="result10" class="result">
<div class="main">Result 10</div>
<div class="details">Details for result 10</div>
</div>
</div>
</div>
A complete working example on CodePen, if you prefer.

Related

Passing Javascript value into CSS?

I'm trying to pass my javascript value (a percentage) into the css 100% width line which is currently at 30%. This currently creates a table that populates outward, starting at 0 and then going out to 30%, I want to be able to implement my Javascript value (c2_percent) instead of the 30% value. If anyone can help that would be great. Thanks
<div class="bar-graph bar-graph-horizontal bar-graph-one">
<div class="bar-one">
<span class="rating-a1">A1</span>
<div class="bar" id="rating-a1" data-percentage=""></div>
</div>
<div class="bar-two">
<span class="rating-a2">A2</span>
<div class="bar" data-percentage="11%"></div>
</div>
<div class="bar-three">
<span class="rating-a3">A3</span>
<div class="bar" data-percentage="7%"></div>
</div>
<div class="bar-four">
<span class="rating-b1">B1</span>
<div class="bar" data-percentage="10%"></div>
</div>
<div class="bar-five">
<span class="rating-b2">B2</span>
<div class="bar" data-percentage="20%"></div>
</div>
<div class="bar-six">
<span class="rating-b3">B3</span>
<div class="bar" data-percentage="5%"></div>
</div>
<div class="bar-seven">
<span class="rating-c1">C1</span>
<div class="bar" data-percentage="9%"></div>
</div>
<div class="bar-eight">
<span class="rating-c2">C2</span>
<div class="bar" id="c2-rating" data-percentage=""></div>
</div>
<div class="bar-nine">
<span class="rating-c3">C3</span>
<div class="bar" data-percentage="5%"></div>
</div>
<div class="bar-ten">
<span class="rating-d1">D1</span>
<div class="bar" data-percentage="5%"></div>
</div>
</div>
#-webkit-keyframes show-bar-eight {
0% {
width: 0;
}
100% {
width: 30%;
}
}
<script>
for(let i = 0; i < 1; i++) {
const c2_security_values = Array.from(document.querySelectorAll('.security-value-c2'));
const c2_security_values_inner = c2_security_values.map((element) => element.innerText);
const c2_summed_values = c2_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue));
const total_security_values = Array.from(document.querySelectorAll('.individual-market-value'));
const total_security_values_inner = total_security_values.map((element) => element.innerText);
const total_summed_values = total_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue));
const c2_percent = c2_summed_values / total_summed_values
}
</script>
Out of the top of my head, I would add this line after calculating c2_percent in the script (make sure to have your c2_percent defined outside of the loop, and set it as a variable, not a constant).
document.getElementById('c2-rating').setAttribute("data-percentage", c2_percent * 100 + '%');
As you don't provide any other data about the rest of the page, the styles, etc. I cannot tell if this would even work.
Do you pretend to modify the width of the c2-rating?
This only modifies the value of the data-percentage attribute.
To modify the css width attribute, you can try
document.getElementById('c2-rating').setAttribute("style","width:" + (c2_percent * 100) + '%');
I have made a snippet that shows that it would work, it all will depend on the rest of the page in your project.
<html>
<head>
<style>
.bar-graph {
font-family: Arial, Helvetica, sans-serif;
}
.bar-graph div {
padding: 5px 0px;
}
.bar-graph div span {
display: inline-block;
font-weight: 600;
margin: 5px 5px;
float: left;
}
.bar-graph .bar {
border: 1px solid #ccc;
background-color: #eee;
height: 30px;
}
#-webkit-keyframes show-bar-eight {
0% {
width: 0;
}
100% {
width: 30%;
}
}
</style>
</head>
<body>
<div class="bar-graph bar-graph-horizontal bar-graph-one">
<div class="bar-one">
<span class="rating-a1">A1</span>
<div class="bar" id="rating-a1" data-percentage=""></div>
</div>
<div class="bar-two">
<span class="rating-a2">A2</span>
<div class="bar" data-percentage="11%"></div>
</div>
<div class="bar-three">
<span class="rating-a3">A3</span>
<div class="bar" data-percentage="7%"></div>
</div>
<div class="bar-four">
<span class="rating-b1">B1</span>
<div class="bar" data-percentage="10%"></div>
</div>
<div class="bar-five">
<span class="rating-b2">B2</span>
<div class="bar" data-percentage="20%"></div>
</div>
<div class="bar-six">
<span class="rating-b3">B3</span>
<div class="bar" data-percentage="5%"></div>
</div>
<div class="bar-seven">
<span class="rating-c1">C1</span>
<div class="bar" data-percentage="9%"></div>
</div>
<div class="bar-eight">
<span class="rating-c2">C2</span>
<div class="bar" id="c2-rating" data-percentage=""></div>
</div>
<div class="bar-nine">
<span class="rating-c3">C3</span>
<div class="bar" data-percentage="5%"></div>
</div>
<div class="bar-ten">
<span class="rating-d1">D1</span>
<div class="bar" data-percentage="5%"></div>
</div>
</div>
<input type="range" min="0" max="100" value="0" class="slider" id="c2RatingSlider" value="43" onchange="updateC2()">
<script>
updateC2();
function updateC2() {
var c2_percent = document.getElementById("c2RatingSlider").value / 100;
document.getElementById('c2-rating').setAttribute("data-percentage", c2_percent * 100 + '%');
document.querySelectorAll('.bar').forEach((bar) => {
const percentage = bar.getAttribute('data-percentage');
bar.setAttribute("style", "width:" + percentage);
});
}
</script>
</body>
</html>

How to make infinite Scrolling?

I am creating a Slider with horizontal Scrolling effect But I stuck at a point how Can I make the slider scroll infinitely Like in my code you can see After Item 6 it stops Scrolling and I have to scroll backward but I want it like after Item 6, Item 1 will come again Something like this https://durimel.io/nel Here you can see the scrolling is infinite?
So can anyone help in this?
let container = document.querySelector(".container")
let container1 = document.querySelector(".container1")
window.onscroll = ()=>{
container.style.left = `${-window.scrollY}px`
container1.style.right = `${-window.scrollY}px`
}
let currentpos = container.getBoundingClientRect().left
let currentpos1 = container1.getBoundingClientRect().left
let callDisort = () =>{
let newPos = container.getBoundingClientRect().left;
let newPos1 = container1.getBoundingClientRect().left;
let diff = newPos - currentpos;
let speed = diff * 0.50
container.style.transform = `skewX(${speed}deg)`
currentpos = newPos
container1.style.transform = `skewX(${speed}deg)`
currentpos = newPos
requestAnimationFrame(callDisort)
}
console.log(currentpos)
callDisort()
*{
margin:0;
padding:0;
box-sizing:border-box;
font-family: arial;
}
html,body{
height:3000px;
overflow-X:hidden;
}
.container{
position:fixed;
display:flex;
justify-content: space-between;
top:30vh;
width: 3000px;
transition:transform 0.15s;
will-change:transform;
border:2px solid green;
}
.container1{
position:fixed;
display:flex;
justify-content: space-evenly;
top:45vh;
width: 3000px;
transition:transform 0.15s;
will-change:transform;
border:2px solid green;
}
.box{
position:relative;
}
.box h2{
font-size:4em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="box one">
<h2>Item 1</h2>
</div>
<div class="box two">
<h2>Item 2</h2>
</div>
<div class="box three">
<h2>Item 3</h2>
</div>
<div class="box four">
<h2>Item 4</h2>
</div>
<div class="box five">
<h2>Item 5</h2>
</div>
<div class="box six">
<h2>Item 6</h2>
</div>
</div>
<div class="container1">
<div class="box one">
<h2>Item 1</h2>
</div>
<div class="box two">
<h2>Item 2</h2>
</div>
<div class="box three">
<h2>Item 3</h2>
</div>
<div class="box four">
<h2>Item 4</h2>
</div>
<div class="box five">
<h2>Item 5</h2>
</div>
<div class="box six">
<h2>Item 6</h2>
</div>
</div>
</body>
</html>
The method the example (https://durimel.io/nel) uses differs and is not really infinite. It is limited to the max values the css properties left and transform: translate3d() support. But its enough for a normal use.
It changes the position of each box as soon as it is out of view depending on the direction and moving it behind the "last" or before the "first" using transform: translate3d() and left: ....
Overall here is version of the method i mentioned. I recommend testing it in on jsfiddle or run the snippet in "Full Page"-View because of the mouse-wheel-scrolling behavior from unscrollable iframe-childs and a scrollable parents can't be prevented.
Update:
Added a simple speed detection routine to allow faster/slower scrolling.
Also fixed the selector for the observer at the end of the js part
const eventHandler = (e) => {
document.querySelectorAll(".boxes-container").forEach(container => {
const cur = +container.dataset.cur || 0;
container.dataset.before = container.dataset.cur;
container.dataset.scrollspeed = (+container.dataset.scrollspeed || 0) +1;
setTimeout(() => {
container.dataset.scrollspeed = +container.dataset.scrollspeed -1;
}, 33 * +container.dataset.scrollspeed);
let moveByPixels = Math.round(e.deltaY / (6 - Math.min(+container.dataset.scrollspeed,5)));
if (container.dataset.direction == "invert") {
moveByPixels *= -1;
}
container.style.left = `${cur + -moveByPixels}px`;
container.dataset.cur = cur + -moveByPixels;
});
};
window.addEventListener("wheel", eventHandler);
window.addEventListener("mousewheel", eventHandler);
const observer = new IntersectionObserver((entries, opts) => {
entries.forEach(entry => {
entry.target.classList.toggle('visible', entry.isIntersecting);
});
document.querySelectorAll(".boxes-container").forEach(container => {
const before = (+container.dataset.before || 0),
current = (+container.dataset.cur || 0),
diff = before - current,
boxes = [...container.querySelectorAll(".box")],
visible = [...container.querySelectorAll(".box.visible")],
first = boxes.indexOf(visible[0]),
last = boxes.indexOf(visible[visible.length - 1]),
adjust = (by) => {
container.dataset.cur = +container.dataset.cur + by;
container.dataset.before = +container.dataset.before + by;
container.style.left = +container.dataset.cur + 'px';
};
if (diff >= 0) {
if (first > 0) { // move the first to the end
const box = boxes[0];
box.parentNode.append(box);
adjust(box.clientWidth);
}
} else {
if (last == 0 || first == 0) { // move the to first
const box = boxes[boxes.length - 1];
box.parentNode.prepend(box);
adjust(-box.clientWidth);
}
}
})
}, { // trigger on any percent value
threshold: new Array(101).fill(0).map((n, i) => +(i / 100).toFixed(2))
});
document.querySelectorAll(".boxes-container .box").forEach(el => observer.observe(el));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Sans-Serif;
}
.boxes-container {
position: fixed;
display: flex;
flex-wrap: nowrap;
flex-direction: row;
white-space: nowrap;
min-width: -min-content;
}
.v30 {
top: 30vh;
}
.v60 {
top: 60vh;
}
.box {
position: relative;
margin: 0 !important;
padding: 0 50px;
}
.box h2 {
font-size: 5rem;
}
<div class="boxes-container">
<div class="box">
<h2>0</h2>
</div>
<div class="box">
<h2>1</h2>
</div>
<div class="box">
<h2>2</h2>
</div>
<div class="box">
<h2>3</h2>
</div>
<div class="box">
<h2>4</h2>
</div>
<div class="box">
<h2>5</h2>
</div>
<div class="box">
<h2>6</h2>
</div>
</div>
<div class="boxes-container v30" data-direction="invert">
<div class="box">
<h2>A</h2>
</div>
<div class="box">
<h2>B</h2>
</div>
<div class="box">
<h2>C</h2>
</div>
<div class="box">
<h2>D</h2>
</div>
<div class="box">
<h2>E</h2>
</div>
<div class="box">
<h2>F</h2>
</div>
<div class="box">
<h2>G</h2>
</div>
</div>
<div class="boxes-container v60">
<div class="box">
<h2>0</h2>
</div>
<div class="box">
<h2>1</h2>
</div>
<div class="box">
<h2>2</h2>
</div>
<div class="box">
<h2>3</h2>
</div>
<div class="box">
<h2>4</h2>
</div>
<div class="box">
<h2>5</h2>
</div>
<div class="box">
<h2>6</h2>
</div>
</div>
A few comments on this solution.
If the container is set to display:flex; justify-content:space-around; then the space between the items will change as you scroll (the more items, the closer packed they are). Changing to justify-content:flex-start; with a fixed width for each .box delivers the best result.
Adding a debounce fn greatly improved (and simplified) the job. At least, the console logs are underwhelming(!).
If you scroll the scroll wheel very fast, you might hit the end of the carousel before it re-populates. To make that easier to see, change the delay from 50 to 500 (milliseconds).
The debounce is saying, "only plunk more boxes into the container when 50ms has elapsed since the last scroll event. You might prefer a throttle function instead, where it will run at most one re-population every 50ms (or as you set the debounceDelay value).
The HTML,Body height needs to be set to a very large number - in this demo it is now set to 30,000. The .container width should be auto, and it (the .container width) will increase every time new items are plonked into the container.
Most important: the $ and $$ are not jQuery. They are pure vanilla javaScript shorthand for document.querySelector() and document.querySelectorAll()
The demo is best viewed full page (link at top right of demo window).
const $ = document.querySelector.bind(document);
const $$ = document.querySelectorAll.bind(document);
let kontainer = $(".container");
const boxes = $$('.box');
const debounceDelay = 50; //change to 100 for better performance
const updateCarousel = debounce(function(e){
console.log(scrollY +' // '+ kontainer.getBoundingClientRect().right)
const currKontainerWidth = kontainer.getBoundingClientRect().right;
if ( currKontainerWidth - scrollY < 300 ){
for (let i=0, j=boxes.length; j > i; i++){
kontainer.appendChild(boxes[i].cloneNode(true));
}
}
}, debounceDelay);
window.addEventListener('scroll', updateCarousel, false);
window.onscroll = () => {
kontainer.style.left = `${-window.scrollY}px`;
}
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
*{
margin:0;
padding:0;
box-sizing:border-box;
font-family: arial;
}
html,body{
height:30000px;
overflow-X:hidden;
}
.container{
position:fixed;
display:flex;
justify-content: flex-start;
top:30vh;
width: auto;
transition:transform 0.15s;
will-change:transform;
border:2px solid green;
}
.box{
position:relative;
min-width:250px;
}
.box h2{
font-size:4em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="box one">
<h2>Item 1</h2>
</div>
<div class="box two">
<h2>Item 2</h2>
</div>
<div class="box three">
<h2>Item 3</h2>
</div>
<div class="box four">
<h2>Item 4</h2>
</div>
<div class="box five">
<h2>Item 5</h2>
</div>
<div class="box six">
<h2>Item 6</h2>
</div>
</div>
</body>
</html>
Best viewed "full page" (top right link after clicking Run Code Snippet)

trying to get the value of a random number and put it in a specific div

I'm trying to display random number in a specific div or grid do i need to store number first i would like some advice on how i can achieve this. for example if random number is 4 i would like that value in div 4, then if my next random number is 10 place it in div 10
browser example
function lottoNumbers() {
var lottoNums = [];
for (var i = 0; i < 1; i++) {
var temp = Math.floor(Math.random() * 12);
if (lottoNums.indexOf(temp) == -1) {
`enter code here`
lottoNums.push(temp);
document.getElementById('square' + i).innerHTML = lottoNums[i];
} else {
i--;
}
}
}
<body bgcolor="lightblue">
<h1>
<center>GENERATE LOTTO NUMBERS</center>
</h1>
<div class="divContainer">
<div id=square0 class=num></div>
</div>
</br>
<div class="hej">
<div id=square1 class=nums></div>
<div id=square2 class=nums></div>
<div id=square3 class=nums></div>
<div id=square4 class=nums></div>
</div>
</br>
</br>
</br>
</br>
</br>
</br>
</br>
<div class=hei>
<div id=square5 class=nums></div>
<div id=square6 class=nums></div>
<div id=square7 class=nums></div>
<div id=square8 class=nums></div>
</div>
</br>
</br>
</br>
</br>
</br>
</br>
</br>
</br>
<div class="hek">
<div id=square9 class=nums></div>
<div id=square10 class=nums></div>
<div id=square11 class=nums></div>
<div id=square12 class=nums></div>
</div>
<center>
<input id="btn" class="knapp" type="button" value="lotto" onClick="lottoNumbers();">
</cennter>
</body>
</html>
Your number wasn't being placed on the right spot as You generated the temp variable which is the random number, but have addressed it to variable i which is the iterator of the for loop. This way, if You would generate 3 random numbers, they would be placed in the divs square0, square1, square2 when they actually should be placed in the divs 'square'+temp that correspond to the actual generated number. Please see my example:
document.getElementById ("btn").addEventListener ("click", lottoNumbers, false);
function lottoNumbers() {
var lottoNums = [];
for (var i = 0; i < 1; i++) {
var temp = Math.floor(Math.random() * 12) + 1;
lottoNums.push(temp);
document.getElementById('square' + temp).innerHTML = lottoNums[i];
document.getElementById('square0').innerHTML = lottoNums[i];
}
}
.num {
border: 1px solid;
width: 20px;
height: 20px;
margin: 2px;
}
.nums {
border: 1px solid;
width: 20px;
height: 20px;
margin: 2px;
float: left;
}
body {
background-color: lightblue;
}
.hej{
float: left;
width: 120px;
height: 30px;
clear: both;
}
.hei{
float: left;
width: 120px;
height: 30px;
clear: both;
}
.hek{
float: left;
width: 120px;
height: 30px;
clear: both;
}
.divContainer{
float: right;
width: 20px;
height: 20px;
font-size: 15px;
}
<h1>
<center>GENERATE LOTTO NUMBERS</center>
</h1>
<div class="divContainer">
<div id="square0" class="num"></div>
</div>
<div class="hej">
<div id="square1" class="nums"></div>
<div id="square2" class="nums"></div>
<div id="square3" class="nums"></div>
<div id="square4" class="nums"></div>
</div>
<div class="hei">
<div id="square5" class="nums"></div>
<div id="square6" class="nums"></div>
<div id="square7" class="nums"></div>
<div id="square8" class="nums"></div>
</div>
<div class="hek">
<div id="square9" class="nums"></div>
<div id="square10" class="nums"></div>
<div id="square11" class="nums"></div>
<div id="square12" class="nums"></div>
</div>
<input id="btn" class="knapp" type="button" value="lotto"">
You can just change
document.getElementById('square' + i).innerHTML = lottoNums[i];
to
document.getElementById('square' + lottoNums[i]).innerHTML = lottoNums[i];
to put each random number in the div matching that number.

On click scroll up or down 100vh pure javascript

I am trying to implement a simple button that on click will scroll the page either up or down 100vh between my sections. I can see plenty of examples doing this with jQuery but I'm looking for a pure javascript solution. I'm not to sure how to achieve it.
Appreciate any advice.
HTML
<section class="section section-1">
<div class="btn"></div>
</section>
<section class="section section-2">
<div class="btn"></div>
</section>
<section class="section section-3">
<div class="btn"></div>
</section>
CSS
.section {
width: 100%;
height: 100vh:
}
This is what I have come up with so far
for (var s = 0; s < btn.length; s++) {
btn[s].addEventListener('click', function(){
window.scrollBy(0,1000);
});
}
There are a few ways to get viewport size in JavaScript. Using one of these ways, you should be able to scroll as you are with the viewport size in place of your 1000.
For instance, if I wanted to scroll exactly the height of one viewport with window.innerHeight:
let pageHeight = window.innerHeight;
window.scrollBy(0, pageHeight);
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', function() {
let scrollDistance = document.documentElement.clientHeight;
if (btn.className.split(' ').includes('scroll-up')) {
scrollDistance *= -1;
}
window.scrollBy(0, scrollDistance);
});
});
body {
margin: 0;
}
.section {
width: 100%;
height: 100vh;
}
.section-1 {
background-color: blue;
}
.section-2 {
background-color: red;
}
.section-3 {
background-color: green;
}
<section class="section section-1">
<div class="btn scroll-down">V</div>
<div class="btn scroll-up">^</div>
</section>
<section class="section section-2">
<div class="btn scroll-down">V</div>
<div class="btn scroll-up">^</div>
</section>
<section class="section section-3">
<div class="btn scroll-down">V</div>
<div class="btn scroll-up">^</div>
</section>

Getting divs next to each other when clicking on a button / JQuery

i am making a kind of storyboard where you can add and remove frames but i need to set divs next to each other, the code i now have it places the div's beneath each other. I want to make it with a loop
Here is my code:
HTML
<div id="storyboard">
<div id="container">
<div class="frame">
<div class="frame__outer">
<div class="frame__inner"></div>
<div class="frame__content"></div>
<div type="button" value="fade_in" class="add__button"> + </div>
</div>
</div>
</div>
</div>
JS
_this.addClickFunction = function() {
var i = 0;
$('.add__button').click(function() {
$('.frame').after('<div id="container'+(i++)+'"></div> <div class="frame__outer"> <div class="frame__inner"></div><div class="frame__content"></div></div>');
});
};
Use append() instead of after() function. This should work:
_this.addClickFunction = function() {
var i = 0;
$('.add__button').click(function() {
$('.frame').append('<div id="container'+(i++)+'"></div> <div class="frame__outer"> <div class="frame__inner"></div><div class="frame__content"></div></div>');
});
};
This works for keeping one .frame element and adding multiple divs to it of the structure:
<div class="container[i]">
<div class="frame__outer">
<div class="frame__inner"></div>
<div class="frame__content"></div>
</div>
</div>
If you want to arrange elements side by side which normaly are block elements and thus are positioned underneath eachother by default use either css floats or css flexbox.
https://css-tricks.com/all-about-floats/
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
i need to set divs next to each other
Try this example to add new story container to all current .container
var i = 1;
$('.add__button').click(function() {
i++;
$(".container").each(function(x) {
$(this).after('<div id="container' + x + '_' + i + '" class="container"><div class="frame"><div class="frame__outer"> <div class="frame__inner"></div><div class="frame__content">story ' + i + '</div></div></div></div>');
});
});
.frame__outer {
padding: 20px;
background: #222;
color: white;
border-bottom: solid 3px green;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="storyboard">
<input type='button' value='add story' class="add__button" />
<div id="container" class='container'>
<div class="frame">
<div class="frame__outer">
<div class="frame__inner"></div>
<div class="frame__content">story 1</div>
</div>
</div>
</div>
</div>

Categories