here i'm facing some issue in scrolling
i have made one custom selection value through drum design with scrolling(that you can see on live code) issue
1.parent div scrolling while selecting the values in child component by scrolling
what i tried method-1
i have tried the some kind of css methods like {overflow-y : scroll , position fixed} but no use, because i thought i have used the onWheel event insted of onScroll according to code needs
Method-2
i tried this method with the mouseover
and mouseout
event
here is the functionality in each block
mouseover
const mouseHoverHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.classList.add("containerScrollFiller");
};
here while mouseover on the component i just adding one class to desable scroll bar with hiden and adding one filler in the place of scroll strip by using Css ::after
class
here is the containerScrollFiller
class property in css file
.containerScrollFiller{
overflow-y: hidden ;
}
.containerScrollFiller::after{
position: absolute;
top: 0;
right: 0;
background-color: lightgray;
width: .5rem;
height: 100%;
content: "";
border-radius: .6rem;
}
here is the mouseOut block
mouseOut
const mouseOutHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.classList.remove("containerScrollFiller");
};
here im simply removing the class from the classlist
this method is working partially but UI shaking while mouseOut and mouseOver the component continiously. This looks little wiere (you can see this issue on live code below)
how can we stop the scrolling without hiding or removing the scroll bar
const CustomCalender = () => {
// let index = 1;
let getPeriod = { value1: "", value2: "", value3: "", value4: "" };
let index = [1, 1, 1, 1];
function scrollClass(event, array, td, md, bd, pt, objPt) {
var elementMd = document.getElementById(md);
var elementTo = document.getElementById(td);
var elementBo = document.getElementById(bd);
console.log(index[pt]);
index[pt] = event < 0 ? index[pt] : event > 0 ? --index[pt] : index[pt];
index[pt] =
index[pt] > array.length - 1
? 0
: index[pt] < 0
? array.length - 1
: index[pt];
elementMd.innerHTML = array[index[pt]];
elementTo.innerHTML =
array[index[pt] 1] === undefined ? array[0] : array[index[pt] 1];
elementBo.innerHTML =
array[index[pt] - 1] === undefined
? array[array.length - 1]
: array[index[pt] - 1];
getPeriod[objPt] = array[index[pt]];
}
const colors = [
"Dec",
"Nov",
"Oct",
"Sep",
"Aug",
"Jul",
"Jun",
"May",
"Apr",
"Mar",
"Feb",
"Jan",
];
const year = ["2025", "2024", "2023", "2022", "2021", "2020", "2019"];
const changeValueByWheel = (e, ar, td, md, bd, pt, objPlace) => {
scrollClass(e.deltaY, ar, td, md, bd, pt, objPlace);
};
const changeItem = (payload, ar, td, md, bd, pt, objPlace) => {
scrollClass(-payload, ar, td, md, bd, pt, objPlace);
};
const getCustomDate = () => {
console.log(getPeriod);
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.classList.remove("containerScrollFiller");
};
// demandForeCastingScrollFiller
const mouseOutHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.setAttribute("style", "overflow-y:scroll");
parentScrollableDiv.classList.remove("containerScrollFiller");
};
const mouseHoverHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.setAttribute("style", "overflow-y:hidden");
parentScrollableDiv.classList.add("containerScrollFiller");
};
return (
<div className="container">
<h4>What is Lorem Ipsum?</h4>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
<div
onm ouseLeave={mouseOutHandle}
onm ouseOver={mouseHoverHandle}
className="customCalenderContainer"
>
<div id="showItem" className="DemoContainer">
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
className="monthDiv"
>
<div
onClick={() =>
changeItem(
1,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
id="startMonthTopEle"
></div>
<div id="startMonthMiddleEle">{colors[colors.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
id="startMonthBottomEle"
>
{colors[colors.length - 2]}
</div>
</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
className="monthDiv"
>
<div
id="startYearTopEle"
onClick={() =>
changeItem(
1,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
></div>
<div id="startYearMiddleEle">{year[year.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
id="startYearBottomEle"
>
{year[year.length - 2]}
</div>
</div>
<div className="middleDis">TO</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
className="monthDiv"
>
<div
id="endMonthTopEle"
onClick={() =>
changeItem(
1,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
></div>
<div id="endMonthMiddleEle">{colors[colors.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
id="endMonthBottomEle"
>
{colors[colors.length - 2]}
</div>
</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
className="monthDiv"
>
<div
id="endYearTopEle"
onClick={() =>
changeItem(
1,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
></div>
<div id="endYearMiddleEle">{year[year.length - 2]}</div>
<div
onClick={() =>
changeItem(
-1,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
id="endYearBottomEle"
>
{year[year.length - 3]}
</div>
</div>
</div>
<div className="calanderButtonContainer">
<button className="applyBtnCalender" onClick={getCustomDate}>
Apply
</button>
</div>
</div>
<h4>What is Lorem Ipsum?</h4>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
</div>
);
};
//==========================================
ReactDOM.createRoot(
document.getElementById("root")
).render(
<CustomCalender/>
);
.container{
width: 30rem;
height: 20rem;
background-color: white;
border: 1px solid gray;
overflow-y: scroll;
margin: auto auto;
background-color: purple;
color: white;
position: relative;
}
.container::-webkit-scrollbar{
width: .5rem;
/* background-color: green; */
}
.container::-webkit-scrollbar-thumb {
background: lightgray;
border-radius: .6rem;
}
.container::-webkit-scrollbar-thumb:hover {
background: #d8d8d8;
border-radius: .6rem;
}
.customCalenderContainer{
width: 15rem;
height: 12rem;
border-radius: .3rem;
background-color: black;
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: space-evenly; */
justify-content: flex-start;
border: .01rem solid #f0f1f2;
margin: 2rem auto;
padding-top: 1rem;
}
.DemoContainer{
width: 13rem;
height: 8rem;
border-radius: .3rem;
background-color: white;
display: flex;
align-items: center;
justify-content: space-around;
margin: 0 auto;
}
.monthDiv{
height: 8rem;
width: 3rem;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
/* background-color: black; */
cursor: all-scroll;
}
#startMonthMiddleEle,
#startYearMiddleEle,
#endMonthMiddleEle,
#endYearMiddleEle{
border-bottom: .1rem solid #868686;
border-top: .1rem solid #868686;
font-weight: 700;
color: #717171;
padding: .3rem 0;
width: 80%;
text-align: center;
font-size: .9rem;
transition: 1s ease-in-out;
/* transform : translateY(-20px) */
}
#startMonthTopEle,
#startMonthBottomEle,
#startYearTopEle,
#startYearBottomEle,
#endMonthTopEle,
#endMonthBottomEle,
#endYearTopEle,
#endYearBottomEle{
font-weight: 500;
font-size: .6rem;
transition: 1s ease-in-out;
color: #9d9d9d;
/* background-color: green; */
height: 2rem;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.middleDis{
height: 9rem;
width: 2rem;
/* background-color: rgb(200, 254, 200); */
align-items: center;
display: flex;
justify-content: center;
font-weight: bolder;color: #717171;
}
.calanderButtonContainer{
width: 13rem;
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
.applyBtnCalender{
background-color: orange;
color: white;
/* margin-top: -4vh; */
padding: 0.6em 1.1em;
font-size: .7rem;
font-family: 'Roboto', sans-serif;
border: none;
border-radius: .3rem;
cursor: pointer;
}
.containerScrollFiller::after{
position: absolute;
top: 0;
right: 0;
background-color: lightgray;
width: .5rem;
height: 100%;
content: "";
border-radius: .6rem;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
any help is so appreciatable
thanks advance !!
CodePudding user response:
Since I'm not very good at react, I've reduced your example to a simple HTML / CSS / JS example.
But it's basically still the same, as you want to keep the outer container from scrolling as soon as you enter your date select.
So basically, you need two events on your date select. Just as you already mentioned in your post, one when you enter the element and one when you exit it.
mouseenter
on date select: when this event fires, you wan't to prevent your outer container from scrolling. In order to do so, you add a new eventListener to the outer container, listening on the wheel
event.
In the event function you prevent the default behaviour with e.preventdefault()
and stop bubbling up the event with e.stopPropagation
.
mouseout
on date select: when you exit your date select, you want to remove the previously added eventListener from the scroll container. You can do this with removeEventListener()
. This lets you scroll again as soon as you are no longer hovering the element.
Note: In order to remove an eventlistener, you have to use named functions for your events. Thus we are defining it with function preventScroll()
Note 2: As long as you don't move your mouse and are just scrolling, the mouseenter
event will not fire, so you can keep on scrolling over the element without getting stuck on it
Note 3: In case you want the same behavour for mobile users, you might want additional eventlisteners, for example sa soon as they start using the date select. You'll have to define them seperately but the basic concept will be the same.
Minimal working example below, same can be applied to react apps as well
function preventScroll(e){
// preventDefault keeps the element from scrolling
e.preventDefault();
// stopPropagation keeps the event to bubble up and scroll an outer container
e.stopPropagation();
return false;
}
// we get the containers here
const preventScrollElement = document.querySelector('.prevent-scroll');
const scrollContainer = document.querySelector('.container');
// when you enter the element with your mouse, we add another eventlistener the the scrolling container itself
preventScrollElement.addEventListener('mouseenter', () => {
scrollContainer.addEventListener('wheel', preventScroll, {passive: false});
});
// as soon as we leave the element, we remove the eventlistener from the scroll container
preventScrollElement.addEventListener('mouseout', () => {
scrollContainer.removeEventListener('wheel', preventScroll);
});
.container {
height: 200px;
width: 300px;
margin: 0 auto;
border: 1px solid black;
overflow-y: scroll;
}
.prevent-scroll {
width: 100px;
height: 100px;
margin: 0 auto;
background: green;
}
.prevent-scroll:hover {
background: red;
}
<div >
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<div ></div>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
CodePudding user response:
UPDATED
here is the solved react code as like @Hoargarth's logic implementation
i have just removed the depth parent and child propegation bubble event for according to code needs then its woked for me
here is the updated code in react
const CustomCalender = () => {
// let index = 1;
let getPeriod = { value1: "", value2: "", value3: "", value4: "" };
let index = [1, 1, 1, 1];
function scrollClass(event, array, td, md, bd, pt, objPt) {
var elementMd = document.getElementById(md);
var elementTo = document.getElementById(td);
var elementBo = document.getElementById(bd);
console.log(index[pt]);
index[pt] = event < 0 ? index[pt] : event > 0 ? --index[pt] : index[pt];
index[pt] =
index[pt] > array.length - 1
? 0
: index[pt] < 0
? array.length - 1
: index[pt];
elementMd.innerHTML = array[index[pt]];
elementTo.innerHTML =
array[index[pt] 1] === undefined ? array[0] : array[index[pt] 1];
elementBo.innerHTML =
array[index[pt] - 1] === undefined
? array[array.length - 1]
: array[index[pt] - 1];
getPeriod[objPt] = array[index[pt]];
}
const colors = [
"Dec",
"Nov",
"Oct",
"Sep",
"Aug",
"Jul",
"Jun",
"May",
"Apr",
"Mar",
"Feb",
"Jan",
];
const year = ["2025", "2024", "2023", "2022", "2021", "2020", "2019"];
function preventScroll(e) {
// preventDefault keeps the element from scrolling
e.preventDefault();
return false;
}
const changeValueByWheel = (e, ar, td, md, bd, pt, objPlace) => {
scrollClass(e.deltaY, ar, td, md, bd, pt, objPlace);
};
const changeItem = (payload, ar, td, md, bd, pt, objPlace) => {
scrollClass(-payload, ar, td, md, bd, pt, objPlace);
};
const getCustomDate = () => {
console.log(getPeriod);
var parentScrollableDiv = document.querySelector(".container");
};
const mouseOutHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.removeEventListener("wheel", preventScroll);
};
const mouseHoverHandle = () => {
var parentScrollableDiv = document.querySelector(".container");
parentScrollableDiv.addEventListener("wheel", preventScroll, {
passive: false,
});
};
return (
<div className="container">
<h4>What is Lorem Ipsum?</h4>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
<div
onm ouseLeave={mouseOutHandle}
onm ouseOver={mouseHoverHandle}
className="customCalenderContainer"
>
<div id="showItem" className="DemoContainer">
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
className="monthDiv"
>
<div
onClick={() =>
changeItem(
1,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
id="startMonthTopEle"
></div>
<div id="startMonthMiddleEle">{colors[colors.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
colors,
"startMonthTopEle",
"startMonthMiddleEle",
"startMonthBottomEle",
0,
"value1"
)
}
id="startMonthBottomEle"
>
{colors[colors.length - 2]}
</div>
</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
className="monthDiv"
>
<div
id="startYearTopEle"
onClick={() =>
changeItem(
1,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
></div>
<div id="startYearMiddleEle">{year[year.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
year,
"startYearTopEle",
"startYearMiddleEle",
"startYearBottomEle",
1,
"value2"
)
}
id="startYearBottomEle"
>
{year[year.length - 2]}
</div>
</div>
<div className="middleDis">TO</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
className="monthDiv"
>
<div
id="endMonthTopEle"
onClick={() =>
changeItem(
1,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
></div>
<div id="endMonthMiddleEle">{colors[colors.length - 1]}</div>
<div
onClick={() =>
changeItem(
-1,
colors,
"endMonthTopEle",
"endMonthMiddleEle",
"endMonthBottomEle",
2,
"value3"
)
}
id="endMonthBottomEle"
>
{colors[colors.length - 2]}
</div>
</div>
<div
onWheelCapture={(e) =>
changeValueByWheel(
e,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
className="monthDiv"
>
<div
id="endYearTopEle"
onClick={() =>
changeItem(
1,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
></div>
<div id="endYearMiddleEle">{year[year.length - 2]}</div>
<div
onClick={() =>
changeItem(
-1,
year,
"endYearTopEle",
"endYearMiddleEle",
"endYearBottomEle",
3,
"value4"
)
}
id="endYearBottomEle"
>
{year[year.length - 3]}
</div>
</div>
</div>
<div className="calanderButtonContainer">
<button className="applyBtnCalender" onClick={getCustomDate}>
Apply
</button>
</div>
</div>
<h4>What is Lorem Ipsum?</h4>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
</div>
);
};
//==========================================
ReactDOM.createRoot(
document.getElementById("root")
).render(
<CustomCalender/>
);
.container{
width: 30rem;
height: 20rem;
background-color: white;
border: 1px solid gray;
overflow-y: scroll;
margin: auto auto;
background-color: purple;
color: white;
position: relative;
}
.container::-webkit-scrollbar{
width: .5rem;
/* background-color: green; */
}
.container::-webkit-scrollbar-thumb {
background: lightgray;
border-radius: .6rem;
}
.container::-webkit-scrollbar-thumb:hover {
background: #d8d8d8;
border-radius: .6rem;
}
.customCalenderContainer{
width: 15rem;
height: 12rem;
border-radius: .3rem;
background-color: black;
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: space-evenly; */
justify-content: flex-start;
border: .01rem solid #f0f1f2;
margin: 2rem auto;
padding-top: 1rem;
}
.DemoContainer{
width: 13rem;
height: 8rem;
border-radius: .3rem;
background-color: white;
display: flex;
align-items: center;
justify-content: space-around;
margin: 0 auto;
}
.monthDiv{
height: 8rem;
width: 3rem;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
/* background-color: black; */
cursor: all-scroll;
}
#startMonthMiddleEle,
#startYearMiddleEle,
#endMonthMiddleEle,
#endYearMiddleEle{
border-bottom: .1rem solid #868686;
border-top: .1rem solid #868686;
font-weight: 700;
color: #717171;
padding: .3rem 0;
width: 80%;
text-align: center;
font-size: .9rem;
transition: 1s ease-in-out;
/* transform : translateY(-20px) */
}
#startMonthTopEle,
#startMonthBottomEle,
#startYearTopEle,
#startYearBottomEle,
#endMonthTopEle,
#endMonthBottomEle,
#endYearTopEle,
#endYearBottomEle{
font-weight: 500;
font-size: .6rem;
transition: 1s ease-in-out;
color: #9d9d9d;
/* background-color: green; */
height: 2rem;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.middleDis{
height: 9rem;
width: 2rem;
/* background-color: rgb(200, 254, 200); */
align-items: center;
display: flex;
justify-content: center;
font-weight: bolder;color: #717171;
}
.calanderButtonContainer{
width: 13rem;
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
.applyBtnCalender{
background-color: orange;
color: white;
/* margin-top: -4vh; */
padding: 0.6em 1.1em;
font-size: .7rem;
font-family: 'Roboto', sans-serif;
border: none;
border-radius: .3rem;
cursor: pointer;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>