Passing Javascript value into CSS? - javascript

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>

Related

Remove a className only the sam parent div

do you know how to keep selected a div in a different column, right every time I click on a div it remove the previous selected. I would like to keep the user choice selected on each different column : [https://codepen.io/dodgpine/pen/bGaqWVG][1]
const subTitleBuild = document.querySelectorAll(".sub-title-build");
const subTitleOs = document.querySelectorAll(".sub-title-os");
const subTitlePackage = document.querySelectorAll(".sub-title-package");
const subTitleLanguage = document.querySelectorAll(".sub-title-language");
const subTitleCuda = document.querySelectorAll(".sub-title-cuda");
const selections = [
subTitleBuild,
subTitleOs,
subTitlePackage,
subTitleLanguage,
subTitleCuda,
];
selections.forEach((selection) => {
selection.forEach((title) => {
title.addEventListener("click", () => {
removeSelectedClasses();
title.classList.add("selected");
});
});
});
function removeSelectedClasses() {
selections.forEach((selection) => {
selection.forEach((title) => {
console.log(title);
title.classList.remove("selected");
});
});
}
I've made two changes to your javascript, which I think achieve what you want (if I have understood correctly, you want a click to apply the class selected without affecting previously selected options, and, presumably, be able to remove earlier selections with another click on them).
Firstly, I commented out (removed) title.classList.remove("selected"); from your removeSelectedClasses() function, as this is what was clearing earlier selections.
Secondly, I modified, title.classList.add("selected"); in your event listeners to instead toggle the selected class on and off using: title.classList.toggle("selected");. This enables a single click to apply the selected class, while a second click on the same box removes it.
The snippet below works to show the effect.
I note you probably need column selections to be limited to a single choice, so you will have to fiddle with how the changes I suggested are applied. But the principle should help you do that.
const subTitleBuild = document.querySelectorAll(".sub-title-build");
const subTitleOs = document.querySelectorAll(".sub-title-os");
const subTitlePackage = document.querySelectorAll(".sub-title-package");
const subTitleLanguage = document.querySelectorAll(".sub-title-language");
const subTitleCuda = document.querySelectorAll(".sub-title-cuda");
const selections = [
subTitleBuild,
subTitleOs,
subTitlePackage,
subTitleLanguage,
subTitleCuda,
];
selections.forEach((selection) => {
selection.forEach((title) => {
title.addEventListener("click", () => {
removeSelectedClasses();
title.classList.toggle("selected");
});
});
});
function removeSelectedClasses() {
selections.forEach((selection) => {
selection.forEach((title) => {
console.log(title);
//title.classList.remove("selected");
});
});
}
.container-master {
width: 1200px;
margin: auto;
}
.container {
display: flex;
justify-content: space-between;
}
.column {
width: 170px;
}
.container-btn {
padding: 20px;
border: 2px solid black;
text-align: center;
margin-top: 10px;
}
.title {
margin-bottom: 30px;
background-color: #3e4652;
color: #ffffff;
}
.sub-title,
.sub-title-build {
cursor: pointer;
}
.row-cmd {
width: 1200px;
margin: 50px auto;
}
.container-btn-cmd {
padding: 20px;
border: 2px solid black;
text-align: center;
margin-top: 10px;
}
.command-container {
padding: 20px;
border: 2px solid black;
text-align: center;
margin-top: 10px;
}
.selected {
background-color: orangered;
color: #ffffff;
}
<div class="container-master">
<div class="container">
<div class="column ptbuild">
<div class="container-btn title">
<div class="btn">PyTorch Build</div>
</div>
<div class="container-btn sub-title-build" id="stable">
<div class="btn">Stable (1.11.0)</div>
</div>
<div class="container-btn sub-title-build" id="preview">
<div class="btn">Preview (Nightly)</div>
</div>
<div class="container-btn sub-title-build" id="lts">
<div class="btn">LTS (1.8.2)</div>
</div>
</div>
<div class="column os">
<div class="container-btn title">
<div class="btn">Your OS</div>
</div>
<div class="container-btn sub-title-os" id="linux">
<div class="btn">Linux</div>
</div>
<div class="container-btn sub-title-os" id="macos">
<div class="btn">Mac</div>
</div>
<div class="container-btn sub-title-os" id="windows">
<div class="btn">Windows</div>
</div>
</div>
<div class="column package">
<div class="container-btn title">
<div class="btn">Package</div>
</div>
<div class="container-btn sub-title-package" id="conda">
<div class="btn">Conda</div>
</div>
<div class="container-btn sub-title-package" id="pip">
<div class="btn">Pip</div>
</div>
<div class="container-btn sub-title-package" id="libtorch">
<div class="btn">LibTorch</div>
</div>
<div class="container-btn sub-title-package" id="source">
<div class="btn">Source</div>
</div>
</div>
<div class="column language">
<div class="container-btn title">
<div class="btn">Language</div>
</div>
<div class="container-btn sub-title-language" id="python">
<div class="btn">Python</div>
</div>
<div class="container-btn sub-title-language" id="cplusplus">
<div class="btn">C++ / Java</div>
</div>
</div>
<div class="column cuda">
<div class="container-btn title">
<div class="btn">Compute Platform</div>
</div>
<div
class="container-btn sub-title-cuda"
id="cuda10.2"
style="text-decoration: line-through"
>
<div class="btn">CUDA 10.2</div>
</div>
<div
class="container-btn sub-title-cuda"
id="cuda11.x"
style="text-decoration: line-through"
>
<div class="btn">CUDA 11.3</div>
</div>
<div
class="container-btn sub-title-cuda"
id="rocm4.x"
style="text-decoration: line-through"
>
<div class="btn">ROCM 4.2 (beta)</div>
</div>
<div class="container-btn sub-title-cuda" id="accnone">
<div class="btn">CPU</div>
</div>
</div>
</div>
<div class="row-cmd">
<div class="container-btn-cmd title">
<div class="option-text">Run this Command:</div>
</div>
<div class="command-container">
<div class="cmd-text" id="command">
<pre># MacOS Binaries dont support CUDA, install from source if CUDA is needed<br>conda install pytorch torchvision torchaudio -c pytorch</pre>
</div>
</div>
</div>
</div>

JavaScript get multiple element's text values

I want to make that when the user clicks onto the bordered container, the 'Name' text should show the container's name only and the 'Subject' text should show the container's subject only, but this code shows all the elements inside the container for the 'Name' and the 'Subject' too.
I mean there are two elements inside one container. One with class 'name' and one with the class 'subject'. When I click onto the bordered container I want to get the 'name' text's and write it into the element with the class resname. And the same thing with the subject. Any idea how to solve it?
var name = document.querySelectorAll('.name');
var gname = $('.resname');
var gsub = $('.ressubject');
$('.container').click(function() {
gname.text($(this).text());
gsub.text($(this).text());
});
.container {
border: 1px solid red;
cursor: pointer;
padding: 5px;
}
.resname, .ressubject {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="header">
<span class="name">firstname</span>
</div>
<div class="body">
<span class="subject">firstsubject</span>
</div>
</div>
<br>
<div class="container">
<div class="header">
<span class="name">secondname</span>
</div>
<div class="body">
<span class="subject">secondsubject</span>
</div>
</div>
<hr><br>
<div class="result">
<span>Name: <span class="resname"></span></span><br>
<span>Subject: <span class="ressubject"></span></span>
</div>
is that what you want?
const container = document.querySelector('.container');
const output = document.querySelector('.output');
const outputItemName = output.querySelector('.output-item > span[data-name]');
const outputItemSubject = output.querySelector('.output-item > span[data-subject]');
container.addEventListener('click', (e) => {
const containerItem = e.target.closest('.container-item');
if (!containerItem) return;
const { name, subject } = containerItem.dataset;
outputItemName.innerText = name;
outputItemSubject.innerText = subject;
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container-inner>* {
margin-bottom: 16px;
}
.container-inner>*:last-of-type {
margin-bottom: 0;
}
.container-item {
padding: 8px;
border: 1px solid black;
cursor: pointer;
}
.output {
margin-top: 16px;
}
<div class="container">
<div class="container-inner">
<div class="container-item" data-name="First name" data-subject="First subject">
<div class="container-item-name">First name</div>
<div class="container-item-subject">First subject</div>
</div>
<div class="container-item" data-name="Second name" data-subject="Second subject">
<div class="container-item-name">Second name</div>
<div class="container-item-subject">Second subject</div>
</div>
</div>
</div>
<div class="output">
<div class="output-inner">
<div class="output-item">
<span>Name:</span>
<span data-name></span>
</div>
<div class="output-item">
<span>Subject:</span>
<span data-subject></span>
</div>
</div>
</div>

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.

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>

Complex continuous scroll loop

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.

Categories