Infinite scroll in Javascript with data from file - javascript

I want to do infinite scroll in plain Javascript. I saw several tutorials but all of them fetch some random data from some api. I understand the code from tutorials but I don't know how to get data in order, not random.
I want to do something similar like here: https://codepen.io/FlorinPop17/pen/RwwvKYJ but I want to use data from my local file. Let's assume it's data.js and has code like it:
data = [{}, {}]
so it's array of objects and let's assume the content of objects is like here: https://jsonplaceholder.typicode.com/posts/
How would you change the code from this codepen to display posts one by one in order? I guess, the function getPost should have parameter "id" and every time this function is called the parameter should be plus 1? But how to do it? Or maybe I should iterate through data.js and on every iteration check if user scrolled to bottom?

You simply have to change the getPost() function to use your inline blog_data which contains all the available posts. The current offset is saved in a global variable post_offset which is increased by every getPost() call so the order will stay the same and no post is shown multiple times.
// all the blog entries that are available
const blog_data = [{
title: "Blog Entry 1",
body: "This is the example body text for entry 1."
},{
title: "This is number two",
body: "Also blog entry number 2 has some content."
},{
title: "Blog entry three",
body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
},{
title: "Blog entry four",
body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
},{
title: "Blog entry five",
body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
},{
title: "Blog entry six",
body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
}];
const container = document.getElementById('container');
const loading = document.querySelector('.loading');
let post_offset = 0;
getPost();
getPost();
getPost();
window.addEventListener('scroll', () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
if(clientHeight + scrollTop >= scrollHeight - 5) {
// show the loading animation
showLoading();
}
});
function showLoading() {
if(post_offset < blog_data.length){
loading.classList.add('show');
// load more data
setTimeout(getPost, 1000)
}
else{
// end has been reached, no more posts available
}
}
async function getPost() {
if(post_offset < blog_data.length){
addDataToDOM(blog_data[post_offset]);
post_offset++;
}
}
function addDataToDOM(data) {
const postElement = document.createElement('div');
postElement.classList.add('blog-post');
postElement.innerHTML = `
<h2 class="title">${data.title}</h2>
<p class="text">${data.body}</p>
`;
container.appendChild(postElement);
loading.classList.remove('show');
}
#import url('https://fonts.googleapis.com/css?family=Open+Sans:300,600&display=swap');
* {
box-sizing: border-box;
}
body {
background-color: #fafafa;
font-family: 'Open Sans', sans-serif;
padding-bottom: 100px;
}
.container {
margin: 0 auto;
max-width: 600px;
}
.blog-post {
background-color: #fff;
box-shadow: 0px 1px 2px rgba(50, 50, 50, .1), 0px 2px 4px rgba(60, 60, 60, 0.1);
border-radius: 4px;
padding: 40px;
margin: 20px 0;
}
.title {
margin: 0;
}
.text {
color: #555;
margin: 20px 0;
}
.loading {
opacity: 0;
display: flex;
position: fixed;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
transition: opacity .3s ease-in;
}
.loading.show {
opacity: 1;
}
.ball {
background-color: #777;
border-radius: 50%;
margin: 5px;
height: 10px;
width: 10px;
animation: jump .5s ease-in infinite;
}
.ball:nth-of-type(2) {
animation-delay: 0.1s;
}
.ball:nth-of-type(3) {
animation-delay: 0.2s;
}
#keyframes jump {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
<div class="container" id="container">
<h1>Blog Posts</h1>
</div>
<div class="loading">
<div class="ball"></div>
<div class="ball"></div>
<div class="ball"></div>
</div>

Related

Change Height (CSS/JS)

Whats wrong with my code? See Tabs 1-2, and then Tab 3.
I recently posted this question: 'How can i change the height of active tabs dynamically?' and received the following code.
As you can see, tab 1 and 2 are working fine. (Posted original question with 2 tabs. But after adding more tabs however, the dynamical change of height is not working anymore. Any suggestions?
Much appreciated
document.getElementById('tab').style.height = document.querySelector(`#tab div`).getBoundingClientRect().height + 'px'
const btn = [].slice.call(document.getElementsByTagName('button'))
btn.forEach((item, index) => {
item.addEventListener('click',function(){
btn.forEach((item) => {item.classList.remove('active')})
item.classList.add('active')
document.getElementById('tab').setAttribute('data-tab', index)
const currentTab = index === 0 ? document.querySelector(`#tab div`) : document.querySelector(`#tab div + div`)
document.getElementById('tab').style.height = currentTab.getBoundingClientRect().height + 'px'
})
}
)
.wrapper {
overflow: hidden;
}
.tabs {
position: relative;
-webkit-transition: all .9s ease-in-out;
-moz-transition: all .9s ease-in-out;
-ms-transition: all .9s ease-in-out;
-o-transition: all .9s ease-in-out;
transition: all .9s ease-in-out;
}
.active {
color:blue;
}
.tabs> * {
width: 100%;
}
.tabs[data-tab='1'] {
transform: translateX(-100%);
}
.tabs[data-tab='2'] {
transform: translateX(-200%);
}
.tabs[data-tab='3'] {
transform: translateX(-300%);
}
.tabs[data-tab='4'] {
transform: translateX(-400%);
}
.inliner {
white-space: nowrap;
}
.inliner > * {
display: inline-block;
*display: inline;
*zoom: 1;
font-size: 1rem;
letter-spacing: normal;
vertical-align: top;
word-spacing: normal;
white-space: normal;
}
<div class="wrapper">
<button> Tab 1</button>
<button> Tab 2</button>
<button> Tab3</button>
<div id="tab" class="tabs inliner">
<div>
<h2>Content 1 </h2>
</div>
<div>
<h2>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam </h2>
</div>
<div> <h3>TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT</h3>
</div>
</div>
</div>
<p>The Height of this text does not keep changing dynamically when clicking Tab no3</p>
I think you should make the variable currentTab point to the correct current tab.just like this
const currentTab = document.querySelector(`#tab div:nth-of-type(${index + 1})`)

Javascript not working on ipad (tested on ios 13.7 and ios 14.0 - in chrome, safari and firefox) or iphone (tested on iphone SE ios 13.7)

I wonder if you can help me please? I am trying to get a a piece of javascript to work on ios devices. I have multiple images on a page in divs and on click I would like to slide across a panel of information (hidden to the left) and once that panel slides in, if that panel is clicked, I would like it to slide back out to the left.
Here is the code I have that works perfectly on all desktop browsers but doesn't do a thing on ios - I can't understand it and am uncertain how to test or check for problems on ios.
Here is a Fiddle: https://jsfiddle.net/adpLqbt2/31/
CSS
.box {
display: inline-block;
position: relative;
width: 500px;
height: 500px;
overflow: hidden;
}
.overlay-btn {
display: inline-block;
position: absolute;
cursor: pointer;
height: 500px;
width: 500px;
z-index: 10;
background: url('../img/icons/info.svg') 98% 98% no-repeat;
}
.overlay-content {
position: absolute;
top: 0;
left: -500px;
width: 500px;
margin: 0;
height: 500px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
}
.over-show {
left: 0;
height: 500px;
transition: all 0.5s ease-out;
-webkit-transition: all 0.5s ease-out;
}
HTML
<div class="box">
<div class="overlay-btn"></div>
<div class="overlay-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
<img src="https://via.placeholder.com/500" alt="rah" />
</div>
<div class="box">
<div class="overlay-btn"></div>
<div class="overlay-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
<img src="https://via.placeholder.com/500" alt="yay" />
</div>
<div class="box">
<div class="overlay-btn"></div>
<div class="overlay-content"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
<img src="https://via.placeholder.com/500" alt="see" />
</div>
JS
const triggers = document.getElementsByClassName('overlay-btn');
const triggerArray = Array.from(triggers).entries();
const panels = document.getElementsByClassName('overlay-content');
const infoButtons = document.getElementsByClassName('overlay-btn');
for (let [index, trigger] of triggerArray) {
let triggerIndex = index;
function togglePanel() {
panels[triggerIndex].classList.toggle('over-show');
infoButtons[triggerIndex].classList.toggle('js-fade');
}
trigger.addEventListener('click', togglePanel);
infoButtons[triggerIndex].addEventListener('click', togglePanel);
}

fading scrollbar when not scrolling

I recently started making a little website project and I'm struggling a bit with customizing my scrollbar.
I got so far that the scrollbar is only visible when you hover over it but that's not exactly my goal. I want it to be hidden when the user didn't scroll for a certain period of time. This is what I got so far:
<style>
::-webkit-scrollbar {
width: 6px;
height: 12px;
}
::-webkit-scrollbar-track {
background: rgba(242, 242, 242, 0);
}
::-webkit-scrollbar-thumb {
background: rgba(221, 221, 221, 0);
border-radius: 3px;
}
/*Commented because I don't want it to show when I just hover the site
body:hover::-webkit-scrollbar-thumb {
background: rgb(0, 0, 0);
}
*/
body.scrolling::-webkit-scrollbar-thumb,
::-webkit-scrollbar-thumb:horizontal:hover,
::-webkit-scrollbar-thumb:vertical:hover {
background: rgb(0, 0, 0);
}
::-webkit-scrollbar-thumb:horizontal:active,
::-webkit-scrollbar-thumb:vertical:active {
background: rgb(0, 0, 0);
}
</style>
<script>$(window).scroll(function() {
$('body').addClass('scrolling');
alert("!!");
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
$('body').removeClass('scrolling');
}, 250));
});</script>
This is my first post on a forum like this so please just tell me if I have to provide more info and which info is missing.
I think its just a typo. Change the closing style tag to </style>. It can't be tested very well if theres an alert popping up every time you scroll. Remove alert("!!"); or change it to console.log("!!");
[LATER]
As you want the scrollbar to fade in and out with a transition, you'll have to use an element that covers it and animate its opacity. It's not possible to put an element above the document's scrollbar though. That's why you have to wrap the whole page inside a div and customize its scrollbar.
document.querySelector('.scroll-box').addEventListener('scroll', hideCoverBar);
document.querySelector('.scroll-box').addEventListener('mousemove', hideCoverBar);
var showTimeout;
function hideCoverBar() {
document.querySelector('.cover-bar').classList.add('hidden');
clearTimeout(showTimeout);
showTimeout = setTimeout(showCoverBar, 1000);
}
function showCoverBar() {
document.querySelector('.cover-bar').classList.remove('hidden');
}
body,
html {
margin: 0;
padding: 0;
font-family: monospace;
}
.main {
padding: 20px;
}
h1 {
font-size: 50px;
margin: 0;
}
p {
font-size: 12px;
margin: 0;
}
img {
display: block;
margin: 0 auto;
padding: 20px;
max-width: 100%;
box-sizing: border-box;
}
.scroll-bar-wrap {
width: 100vw;
position: relative;
}
.scroll-box {
width: 100%;
height: 100vh;
overflow-y: scroll;
}
.scroll-box::-webkit-scrollbar {
width: .4em;
}
.scroll-box::-webkit-scrollbar,
.scroll-box::-webkit-scrollbar-thumb {
overflow: visible;
border-radius: 4px;
}
.scroll-box::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, .2);
}
.cover-bar {
position: absolute;
background: #fff;
pointer-events: none;
height: 100%;
top: 0;
right: 0;
width: .4em;
-webkit-transition: all .5s;
opacity: 1;
}
.cover-bar.hidden {
opacity: 0;
}
<div class="scroll-bar-wrap">
<div class="scroll-box">
<div class="main">
<h1>Lorem ipsum dolor sit amet
</h1>
<img src="http://placekitten.com/600/400" />
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
</p>
</div>
</div>
<div class="cover-bar"></div>
</div>
fiddle: https://jsfiddle.net/71fjr0Lz/

removed Class and want to add it back

I coded a simple javascript "clearning Shopping List" code.
I was able to remove the shopping list and add two messages:
One says that the shopping list has been cleared and one pops up a button that asks if it was a mistake and you want to undo your change.
Now my problem is that when you press the "Undo" button the class doesn't get added back.
// javascript
var shoppingList = document.querySelector(".shoppingCart");
var toggleButton = document.querySelector("button.showList");
var clearedBox = document.querySelector(".clearedBox");
var clearedUndo = document.querySelector("button.clearedUndo");
//Toggle Shopping Cart
toggleButton.addEventListener("click", () => {
shoppingList.remove(".shoppingCart");
clearedBox.style.display = "block";
toggleButton.remove("button.showList");
});
//Undo Removal
clearedUndo.addEventListener("click", () => {
clearedUndo.createClass(".shoppingCart");
});
html, body {
margin: 0;
padding: 0;
margin-left:30px;
}
.clearedBox {
display:none;
}
.clearedMessage {
background:#D66A68;
color: white;
padding:10px;
width:260px;
text-align:center;
border-radius:10px;
}
.clearedUndo {
background:#1C77C3;
color: white;
padding:5px;
width:225px;
border-radius:5px;
text-align:center;
font-size:12px;
}
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>index.html</h1>
<button class="showList">Show</button>
<div class="shoppingCart">
<ul>
<li>Milk</li>
<li>Eggs</li>
<li>Juice</li>
<li>Pasta</li>
<li>Water</li>
<li>Donuts</li>
</ul>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et.</p>
</div>
<div class="clearedBox">
<p class="clearedMessage">Your Shopping cart is now cleared!</p>
<button class="clearedUndo">Accidental? Undo your change!</button>
</div>
<script src="index.js"></script>
</body>
</html>
I would assume this part is wrong:
//Undo Removal
clearedUndo.addEventListener("click", () => {
clearedUndo.createClass(".shoppingCart");
});
Once you remove it, it's gone, and if you want to put it back with JavaScript then all that markup really needs to be re-inserted, so I'd consider just hiding and showing the elements as needed, by changing the JS to this:
var shoppingList = document.querySelector(".shoppingCart");
var toggleButton = document.querySelector("button.showList");
var clearedBox = document.querySelector(".clearedBox");
var clearedUndo = document.querySelector("button.clearedUndo");
//Toggle Shopping Cart
toggleButton.addEventListener("click", () => {
shoppingList.style.display = "none";
clearedBox.style.display = "block";
toggleButton.style.display = "none";
});
//Undo Removal
clearedUndo.addEventListener("click", () => {
shoppingList.style.display = "block";
clearedBox.style.display = "none";
toggleButton.style.display = "block";
});
ISSUE
Don't use the elem.remove .Because if you undo the action no elements are present .For alternatively you can use elem.classList.toggle
// javascript
var shoppingList = document.querySelector(".shoppingCart");
var toggleButton = document.querySelector("button.showList");
var clearedBox = document.querySelector(".clearedBox");
var clearedUndo = document.querySelector("button.clearedUndo");
//Toggle Shopping Cart
toggleButton.addEventListener("click", () => {
shoppingList.classList.toggle('hide')
clearedBox.classList.toggle('show')
//toggleButton.remove("button.showList");
});
//Undo Removal
clearedUndo.addEventListener("click", () => {
shoppingList.classList.toggle('hide')
clearedBox.classList.toggle('show')
});
html,
body {
margin: 0;
padding: 0;
margin-left: 30px;
}
.clearedBox {
display: none;
}
.hide{
display: none;
}
.show{
display: block;
}
.clearedMessage {
background: #D66A68;
color: white;
padding: 10px;
width: 260px;
text-align: center;
border-radius: 10px;
}
.clearedUndo {
background: #1C77C3;
color: white;
padding: 5px;
width: 225px;
border-radius: 5px;
text-align: center;
font-size: 12px;
}
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>index.html</h1>
<button class="showList">Show</button>
<div class="shoppingCart">
<ul>
<li>Milk</li>
<li>Eggs</li>
<li>Juice</li>
<li>Pasta</li>
<li>Water</li>
<li>Donuts</li>
</ul>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et.</p>
</div>
<div class="clearedBox">
<p class="clearedMessage">Your Shopping cart is now cleared!</p>
<button class="clearedUndo">Accidental? Undo your change!</button>
</div>
<script src="index.js"></script>
</body>
</html>

Scale texts of different lengths to fit container width

I have an element with a certain size, that contains texts of single or multiple lines in different lengths. Now I want to scale the font-size of these texts in such a way, that the longest line of the text fits perfectly into the containers width.
As an example, I want this markup
.container {
width: 400px;
border: 1px solid green;
padding: .5em;
}
.container>div {
border: 1px dotted gray;
}
<div class="container">
<div>Lorem ipsum dolor sit amet.</div>
<div>Lorem ipsum.</div>
<div>Lorem ipsum dolor sit amet, consetetur sadipscing elitr,<br />sed diam nonumy eirmod tempor invidunt<br />ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
</div>
produce something like this:
I tried using relative font sizing unit, but always ended up adjusting the font-size of every child element manually, which isn't an option.
Also this post about dynamically scaling text to fit the viewport doesn't help, since I have multiple different text lengths.
Can this be solved with CSS? Or do I have to take a Javascript approach where I count the letters and adjust the font-size accordingly? But what if I use a font where letters have different sizes?
How about this?
$(document).ready(function() {
var divEls = $('.container div');
for(var i=0; i<divEls.length;i++){
var span = $(divEls[i]).find('span');
var fontSize = 16;
while (span.width() < $(divEls[i]).width()) {
span.css('font-size', fontSize++)
}
// wrap if span exceeds div width
if (span.width() > $(divEls[i]).width()) {
span.css('white-space', 'pre-wrap');
}
}
});
.container {
width: 400px;
border: 1px solid green;
padding: .5em;
}
.container>div {
border: 1px dotted gray;
white-space: pre;
}
<div class="container">
<div><span>Lorem ipsum dolor sit amet.</span></div>
<div><span>Lorem ipsum.</span></div>
<div><span>Lorem ipsum dolor sit amet, consetetur sadipscing elitr,<br />sed diam nonumy eirmod tempor invidunt<br />ut labore et dolore magna aliquyam erat, sed diam voluptua .</span></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can also try an ES6 solution like this CodePen Demo
Update - per the comment below, here is a reponsive solution (also see this CodePen Demo):
function resizeFont() {
var divEls = $(".container div");
for (var i = 0; i < divEls.length; i++) {
var span = $(divEls[i]).find("span");
var fontSize = (span.css("font-size").match(/\d+/)[0]);
while (span.width() < $(divEls[i]).width()) {
span.css("font-size", fontSize++);
}
while (span.width() > $(divEls[i]).width()) {
span.css("font-size", fontSize--);
}
}
}
$(document).ready(function() {
resizeFont();
$(window).on("resize", resizeFont);
});
body {
margin: 0;
}
.container {
max-width: 100vw;
border: 1px solid green;
padding: .5em;
}
.container>div {
border: 1px dotted gray;
white-space: pre;
}
<div class="container">
<div><span>Lorem ipsum dolor sit amet.</span></div>
<div><span>Lorem ipsum.</span></div>
<div><span>Lorem ipsum dolor sit amet, consetetur sadipscing elitr,<br />sed diam nonumy eirmod tempor invidunt<br />ut labore et dolore magna aliquyam erat, sed diam voluptua .</span></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories