ReactJS Scroll element a set amount of pixals - javascript

How do I Scroll an element (not the entire page) a specific amount of pixals for example 100px on every click of a button (not a has link because it needs to be a fixed amount of pixals each time) I use ReactJS 16.

You can use scrollBy on the element you want to scroll. A vanilla JS example:
let btn = document.getElementById('btn');
let box = document.getElementById('box');
btn.addEventListener('click', function() {
box.scrollBy({top:100, behavior: "smooth"});
});
#box {
width: 300px;
height: 100px;
overflow-y: scroll;
}
#inner-box {
width: 100px;
height: 1000px;
}
.content {
height: 50px;
display: block
}
<button id="btn">scroll</button>
<div id="box">
<div id="inner-box">
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
</div>
</div>
This is a ReactJS version:
class Scrollable extends React.Component {
constructor(props) {
super(props);
this.scroll = this.scroll.bind(this);
this.box = React.createRef();
}
scroll() {
this.box.current.scrollBy({top:100, behavior: "smooth"});
}
render() {
return (
<div>
<button onClick={this.scroll}>scroll</button>
<div id="box" ref={this.box}>
<div id="inner-box">
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
</div>
</div>
</div>
);
}
}
Demo at Codepen

Related

how to create milky overlay in vue js

I'm working with Vue 3 and Bootstrap 5.
I have a button and two inputs. When I click the button I want to have a "milky" overlay like following:
How can I achieve this?
Code to work with:
<template>
<div class="row">
<button class="btn btn-dark" #click="overlayMilky()">Button</button>
</div>
<div class="row mt-2">
<div class="col-12">
<span>Input 2</span>
<input class="form-control" />
</div>
<div class="col-12">
<span>Input 3</span>
<input class="form-control" />
</div>
</div>
</template>
<script>
export default {
methods: {
overlayMilky() {
//set overlay to milky
}
}
}
</script>
First, you need to surround the inputs with a container element and give this element position: relative and add to it a child which will be the overlay, this should have position: absolute to be absolute to the container element, also should have width: 100%; height: 100%; top: 0px; left: 0px; to take the full size of the container element and then conditionally with v-if you can show/hide it with a state
<div v-if="showOverlay" class="overlay"></div>
methods: {
overlayMilky() {
this.showOverlay = !this.showOverlay;
//set overlay to milky
},
},
This is a full example of code.
<template>
<div>
<div class="row">
<button class="btn btn-dark" #click="overlayMilky()">Button</button>
</div>
<div class="container">
<div v-if="showOverlay" class="overlay"></div>
<div class="row mt-2">
<div class="col-12">
<span>Input 2</span>
<input class="form-control" />
</div>
<div class="col-12">
<span>Input 3</span>
<input class="form-control" />
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showOverlay: false,
};
},
methods: {
overlayMilky() {
this.showOverlay = !this.showOverlay;
//set overlay to milky
},
},
};
</script>
<style>
.container {
position: relative;
}
.overlay {
position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
background-color: rgba(255, 255, 255, 0.4);
}
</style>
You need to add a data field that will describe the "milky" overlay state.
So all you need to do in the overlayMilky method is to set this.milkyOverlay = true.
Then use this milkyOverlay property to add the milky css class or show milky div on top.

How toggle elements inside this intersection observer?

I have a few elements I want to toggle wth a function, but by some reason I can't make it work. When the toggle function is executed, the console logs "cannot read the property classList of Undefined". But if I log them before the function starts I can see the elements.
Javascript
const toggle = element => {
element.classList.toggle('toggle');
};
let numberOfProyects = document.getElementsByClassName('portfolio__item'),
proyects = [],
for (var i = 0; i < numberOfProyects.length; i++) {
proyects[i] = document.getElementById(`proyect${i+1}`);
console.log(proyects[i]);
new IntersectionObserver(()=>{
toggle(proyects[i])
},{threshold: .6}).observe(proyects[i]);
};
HTML
<div class="portfolio__item toggle" id="proyect1">
<h3 class="portfolio__item-title">Podomoro Timer</h3>
<img class="portfolio__item-img" src="assets/images/Captura de pantalla (316).png">
<div class="portfolio__item-links">
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://js-codetalker.github.io/Timer/" class="portfolio__item-links-overlay-link">
<img src="assets/images/world.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go proyect</p>
</a>
</div>
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://github.com/Js-codetalker/Timer" class="portfolio__item-links-overlay-link">
<img src="assets/images/github.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go github</p>
</a>
</div>
</div>
</div>
<div class="portfolio__item toggle" id="proyect2">
<h3 class="portfolio__item-title">Sample Restaurant</h3>
<img class="portfolio__item-img" src="assets/images/Captura de pantalla (317).png">
<div class="portfolio__item-links">
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://js-codetalker.github.io/restaurant-example/" class="portfolio__item-links-overlay-link">
<img src="assets/images/world.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go proyect</p>
</a>
</div>
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://github.com/Js-codetalker/restaurant-example" class="portfolio__item-links-overlay-link">
<img src="assets/images/github.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go github</p>
</a>
</div>
</div>
</div>
What I want is to create a different observer for each element in order to remove the class "toggle" when it reach the expected space in the viewport
(almost) Always use let instead of var when defining variables inside for loops
Also, you don't need store your elements in second array.
const toggle = element => {
element.classList.toggle('toggle');
console.log(element);
};
const proyects = document.getElementsByClassName('portfolio__item');
for (let i = 0; i < proyects.length; i++) {
new IntersectionObserver(() => {
toggle(proyects[i])
}, {
threshold: .6
}).observe(proyects[i]);
};
.container
{
border: 1px solid black;
resize: both;
overflow: auto;
width: 20em;
height: 10em;
}
.container > :after
{
content: attr(id) " class is " attr(class);
}
.container > :not(.toggle) {
background-color: pink;
}
.container >.toggle {
background-color: lightgreen;
}
<div class="container">
<div class="portfolio__item toggle" id="proyect1">
<h3 class="portfolio__item-title">Podomoro Timer</h3>
</div>
<div class="portfolio__item" id="proyect2">
<h3 class="portfolio__item-title">Sample Restaurant (has not toggle by default)</h3>
</div>
<div class="portfolio__item toggle" id="proyect3">
<h3 class="portfolio__item-title">test</h3>
</div>
<div class="portfolio__item toggle" id="proyect4">
<h3 class="portfolio__item-title">test</h3>
</div>
</div>

Finding attributes .on("click") from unrelated div

I'm trying to have it where pressing "btn1" alone populates the sidebar. I tried $("#container").on("click", ".btn1", function() but it doesn't work.
$("#container").on("click", ".item", function() {
$("#title").text($(this).find(".title").text());
var itemImgSrc = $(this).find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
.title and .image are not contained in .btn1. You need to go up to the containing .item and then find them.
$("#container").on("click", ".btn1", function() {
var item = $(this).closest(".item");
$("#title").text(item.find(".title").text());
var itemImgSrc = item.find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
You could also use $(this).siblings(".title') and $(this).siblings(".image").
You need to change $(this) to $(.btn1).
$(this) being the button clicked works for .btn1 and not for .btn2, changing it from dynamic $(this) to always looking for .link in .btn1 should solve it.
Have you tried using $(this).parent().find(".title"). You could move up the heirarchy and get the element from there and then
$("#container").on("click", ".item", function() {
$("#title").text($(this).parent().find(".title").text());
var itemImgSrc = $(this).parent().find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
Also try using an index with the find method. it returns an array but i dont think that giving index is necessary when there is only one element.
something like this
$(this).parent().find(".item")[0].text();

Display div when clicking on another div

I've added three pictures. Look at them please.
What is the best solution to create something like this? I would create after each row a big container and this container is collapsed. After clicking on one of the 3 overlying containers I would fill the container with the text and show it. But what happens when the display can't show 3 divs in a row, because I will use flex boxes? Is there a better solution with much less jquery?
Maybe something like this is a good place to start:
https://jsfiddle.net/547ec3bx/
HTML
<div class="wrapper">
<div class="row">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
<div class="row">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
<div class="row">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
Javascript
document.querySelectorAll('.row').forEach((element, index) => {
element.style.order = index * 2;
});
document.querySelectorAll('.element').forEach(element => {
element.addEventListener('click', event => {
var newRow = document.createElement('div');
newRow.classList.add('row');
newRow.style.order = +event.currentTarget.parentNode.style.order + 1;
var newElement = document.createElement('div');
newElement.classList.add('element');
newRow.appendChild(newElement);
event.currentTarget.parentNode.parentNode.appendChild(newRow);
});
});
CSS
.element {
min-width: 100px;
height: 50px;
flex: 1;
border: 1px solid black;
flex-wrap: nowrap;
}
.row {
width: 350px;
display: flex;
flex-direction: row;
}
.wrapper {
display: flex;
flex-direction: column;
}
you can use javascript to solve this problem , like this ....
html code:
<div id="a">
<h3>wellcome</h3>
</div>
<div id="b">
<h3>hello...</h3>
</div>
javascript code in external file
function goB()
{
document.getElementById("a").style.display="none";
document.getElementById("b").style.display="block";
}
function
{
document.getElementById("b").style.display="none";
document.getElementById("a").style.display="block";
}
Add a div and set its display to Hidden.
Get onclick event for a particular div and set the display property to block
window.addEventListener("load", function(){
document.getElementById("click").onclick = function(){
document.getElementById("div-1").style.display = "block";
};
});
.row
{
width:100%;
}
.one-third
{
width:33.33333%;
float:left;
padding:30px 0;
}
.full-width
{
display:none;
width:100%;
text-align:center;
}
<div class=wrap>
<div class="row">
<div id="click" class="one-third">
Column 1-Click Me
</div>
<div class="one-third">
Column 2
</div>
<div class="one-third">
Column 3
</div>
</div>
<div class="full-width" id="div-1">Full width Div</div>
<div class="row">
<div class="one-third">
Column 1
</div>
<div class="one-third">
Column 2
</div>
<div class="one-third">
Column 3
</div>
</div>

Close a bootstrap row and start new row after every nth containing div

I have a bootstrap row which will be populated by, let's say, blog post thumbnails.
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="navigation">navigation</div>
</section
I want to close a row, insert hr tag and open a new bootstrap row after every 4th post thumbnail.
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="row">
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="navigation">navigation</div>
</section>
Is there a way to do this with jquery?
Can do something like this:
var $mainElem = $('.row'),/* adjust selector to suit page*/
$parent = $mainElem.parent(),
/* remove children after 4th from existing row */
$items = $mainElem.children(':gt(3)').detach();
if ($items.length) {
/* create new row for every 4 items removed above */
for (var i = 0; i < $items.length; i = i + 4) {
var $row = $('<div class="row">').append($items.slice(i, i + 4));
$parent.append('<hr class="divider">').append($row);
}
}
DEMO
This worked best for me:
var $d = $('.thumbs');
var $p = $('.col-sm-3:gt(3)', $d);
if ($p.length) {
$('<div class="row thumbs">').insertAfter($d).append($p);
$('<hr class="divider">').insertAfter($d);
}
Depending on your motivation to wrap each set of columns in a new row, you can style every nth row with straight CSS.
In bootstrap, if you have extra columns that spillover past 12, they just wrap into a new line anyway, so having the new row is usually redundant, although you might have some external reason to keep it in your case.
Either way, here's a CSS solution that adds a page wide horizontal divider every 4 divs:
Demo in jsFiddle & Stack Snippets
.container .row.thumbs div:nth-child(4n) {
position: static;
}
.container .row.thumbs div:nth-child(4n):after {
content: ' ';
border-top: 1px solid black;
display: block;
position: absolute;
width: 95%;
margin-left: 2.5%;
left: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<div class="navigation">navigation</div>
</section>
Also, bear in mind that this won't be natively supported in < IE8

Categories