How to prevent scroll direction? - javascript

Note: This question is an update to How to disable scroll left?.
I'd like to get an div-element that is just scrollable into ONE directions (in my case only "right"). Scrolling to the left direction should get canceled.
I've developed some jQuery code that should be able to prevent the scrolling in the unwanted direction, what kind of is working so far!
But I got some issues because scrolling to the prevented direction obviously looks super sticky & ugly.
let value = $("#parent").scrollLeft()
$("#parent").scroll(function(e) {
let direction = (this.scrollLeft > value) ? 'right' : ((this.scrollLeft === value) ? false : 'left');
console.log(direction)
if (direction == "left") {
this.scrollLeft = value;
e.preventDefault();
e.stopPropagation();
}
value = $("#parent").scrollLeft()
})
#container {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
#parent {
position: relative;
width: 90%;
height: 80%;
overflow-y: hidden;
overflow-x: scroll;
white-space: nowrap;
background: red;
}
.child {
display: inline-block;
position: relative;
margin-left: 3%;
width: 40px;
height: 40px;
background: gray;
}
.as-console-wrapper {
height: 20px!important;
}
.as-console-row {
background: green!important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
<div class="child">9</div>
<div class="child">10</div>
<div class="child">12</div>
<div class="child">13</div>
<div class="child">14</div>
<div class="child">15</div>
<div class="child">16</div>
<div class="child">17</div>
<div class="child">18</div>
<div class="child">19</div>
<div class="child">20</div>
</div>
</div>
Have a look: Scrolling back looks super ugly:
How to fix this?

Related

How to re-create Facebook image modal?

I want to create something almost exactly like the Facebook image modal wherein the image is fixed while a user scrolls through the comments. I am messing with different ways to apply overflow: hidden to one div and overflow: scroll to the other. I even looked into applying it to their parent. Here is the code I've tried:
<div class="row container border border-primary">
<div class="image col border">
Image
</div>
<div class="text-section col border">
Comments
</div>
</div>
div.image {
height: 300px;
overflow: hidden;
}
div.text-section {
height: 1000px;
overflow: scroll;
}
div.container {
height: 300px;
}
Plunkr
I supposed a code like this. The blue (image) remains fixed on the left, while you can scroll the green section (comments) on the right
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#container { background: red; width: 400px; height: 150px; display: flex; }
#image { background: url("https://i1.adis.ws/i/canon/canon-pro-best-landscape-lenses-1-1140?w=200&aspect=4:3&qlt=70&sm=aspect&fmt=jpg&fmt.options=interlaced&fmt=jpg&fmt.options=interlaced&bg=rgb(255,255,255)"); width: 200px; height: 150px; }
#comments { background: #eee; width: 200px; overflow: scroll; padding: 0 10px 20px 10px; font-family: Verdana; color: black; }
</style>
</head>
<body>
<div id="container">
<div id="image"></div>
<div id="comments">
<h3 style="color: red;">Comments</h3>
<p>Nice!</p>
<p>Good!</p>
<p>Wonderful</p>
<p>Bah...</p>
<p>Strange</p>
<p>Nice again</p>
<p>Amazing</p>
<p>Beautiful</p>
<p>Great</p>
<p>I don’t like it</p>
<p>Yes, nice</p>
<p>Super</p>
<p>Normal</p>
<p>Ok...</p>
<p>Nice</p>
<p>Bah</p>
<p>Great</p>
<p>Nice</p>
<p>I like it</p>
<p>Normal</p>
</div>
</div>
</body>
</html>
I don't have facebook so cant look at the behaviour, but you could put position: sticky; on the image container, that will keep it in place. It also depends on your browser support, like ie11 does not support it, but there are more ways to do this. Let me know if you need a more cross browser solution.
.container {
max-height: 600px;
height: 100%;
overflow: auto;
position: relative;
}
div.image {
height: 300px;
background-color: deepskyblue;
position: sticky;
top: 0;
}
div.text-section {
height: 1000px;
background-color: aqua;
}
<div class="row container border border-primary">
<div class="image col border">
Image
</div>
<div class="text-section col border">
Comments
</div>
</div>

Horizantal scroll right to element

I am trying to scroll to right of each element, but could not calculate right of element and scroll to it.
var $scroller = $('.scroller');
$('button').on('click', function() {
var divIdx = $('input').val();
var scrollTo = $('#d' + divIdx)
.css('background', '#9f3')
.position().left;
console.log(scrollTo);
$scroller
.animate({
'scrollLeft': scrollTo
}, 500);
});
.scroller {
width: 300px;
height: 100px;
overflow-x: auto;
overflow-y: hidden;
direction: rtl;
}
.container {
position: relative;
/*important for the .position() method */
height: 100px;
width: 770px;
}
.container div {
height: 90px;
width: 60px;
float: right;
margin: 5px;
background: #39f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroller">
<div class="container">
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
<div id="d5"></div>
<div id="d6"></div>
<div id="d7"></div>
<!-- ... -->
</div>
</div>
<button>Scroll to: </button> <input type="text" value="4" />
How to calculate right of element and scroll to right of element?
How to calculate right of element and scroll to right of element?
How to calculate right of element and scroll to right of element?
You can use this one.
var $scroller = $('.scroller');
$('button').on('click', function() {
var divIdx = $('input').val();
var div = $('#d' + divIdx);
div.css('background', '#9f3');
var divLeft = div.offset().left;
var divWidth = div.width();
var scrollerWidth = $('.scroller').width();
var scrollTo = divLeft - scrollerWidth + divWidth;
$scroller
.animate({
'scrollLeft': scrollTo
}, 500);
});
.scroller {
width: 300px;
height: 100px;
overflow-x: auto;
overflow-y: hidden;
}
.container {
position: relative;
/*important for the .position() method */
height: 100px;
width: 770px;
}
.container div {
height: 90px;
width: 60px;
float: left;
margin: 5px;
background: #39f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroller">
<div class="container">
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
<div id="d5"></div>
<div id="d6"></div>
<div id="d7"></div>
<!-- ... -->
</div>
</div>
<button>Scroll to: </button> <input type="text" value="5" />
You just need to add some right margin and it's all done!
var $scroller = $('.scroller');
$('button').on('click', function() {
var divIdx = $('input').val();
var scrollTo = $('#d' + divIdx)
.css('background', '#9f3')
.position().left;
console.log(scrollTo);
$scroller
.animate({
'scrollLeft': scrollTo
}, 500);
});
.scroller {
width: 300px;
height: 100px;
overflow-x: auto;
overflow-y: hidden;
}
.container {
position: relative;
/*important for the .position() method */
height: 100px;
width: 600px;
}
.container div {
height: 90px;
width: 60px;
float: right;
margin: 5px;
background: #39f;
}
.container div:first-child {
margin-right: 240px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroller">
<div class="container">
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
<div id="d5"></div>
<div id="d6"></div>
<div id="d7"></div>
<!-- ... -->
</div>
</div>
<button>Scroll to: </button> <input type="text" value="4" />
There are two points to consider -
position().left gives you the value of the distance upto left edge of element only. So to get the value upto right edge, you can take left position of the element + the width of the element. $('#d' + divIdx).position().left + $('#d' + divIdx).width()
There should be additional one item's width white space after the last item which allow the scrollbar to move upto the end of the last item.

How to disable scroll left?

I got a div element ("#parent") that includes multiple child elements (".item"). I want to enable scrolling the parent element just in one direction (left OR right). Otherwise nothing should happen.
See my code:
$("#parent").scroll(function() {
// >>> scroll event
// >>> console.log("SCROLLED " + new Date().getMilliseconds())
})
#container {
position: absolute;
width: 100%;
height: 100%;
}
#parent {
position: relative;
width: 90%;
height: 40%;
overflow-y: hidden;
overflow-x: scroll;
white-space: nowrap;
background: red;
}
.child {
display: inline-block;
position: relative;
margin-left: 3%;
width: 40px;
height: 40px;
background: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
<div class="child">9</div>
<div class="child">10</div>
<div class="child">12</div>
<div class="child">13</div>
<div class="child">14</div>
<div class="child">15</div>
<div class="child">16</div>
<div class="child">17</div>
<div class="child">18</div>
<div class="child">19</div>
<div class="child">20</div>
</div>
</div>
So to my question: I'd like to disable scrolling the element to the right hand side (backwards). I'd like to just enable the scroll of the items to the left hand side (forward).
How can I use jQuery to implement this method? Any help would be very appreciated. Thanks in advance!
The following code should do the job1.
previousX stores the last position that the element was scrolled to on the X axis.
When the scroll event triggers, newX is set to the scrollLeft() value (this returns how far the element has been scrolled from it's left-most side, in pixels).
If this value is greater than previousX, then they have scrolled to the right, so we allow the scroll, and update previousX to the new x value.
If the value is lesser than previousX, they have scrolled to the right - so we need to cancel the scroll. To do this, we can use the scrollLeft() function again - but this time, we provide a value to it - this allows us to set the scroll position; rather than retrieve it. By setting it to previousX, we can prevent the scroll.
Note that if the value is equal, we do nothing.
let previousX = -1;
$("#parent").scroll(function(e){
let newX = $("#parent").scrollLeft();
if (newX>previousX) {
previousX = newX;
}
else if (newX<previousX) {
$("#parent").scrollLeft(previousX);
}
})
#container {
position: absolute;
width: 100%;
height: 100%;
overflow:hidden;
}
#parent {
position: relative;
width: 90%;
height: 40%;
overflow-y: hidden;
overflow-x: scroll;
white-space: nowrap;
background: red;
}
.child {
display: inline-block;
position: relative;
margin-left: 3%;
width: 40px;
height: 40px;
background: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
<div class="child">9</div>
<div class="child">10</div>
<div class="child">12</div>
<div class="child">13</div>
<div class="child">14</div>
<div class="child">15</div>
<div class="child">16</div>
<div class="child">17</div>
<div class="child">18</div>
<div class="child">19</div>
<div class="child">20</div>
</div>
</div>
1: Unfortunately, it doesn't seem to work at all when I use it with my Magic Trackpad - but when dragging the scroll bars it works just fine. I haven't tested it on a touch-screen device / Windows / using a proper mouse & scroll wheel, so I don't know how it behaves in those cases either. It would definitely be worth you doing some proper testing / improving this code, as it probably will not work in all cases, or even catch all possible scroll events.

Vertical content slider - JQuery

I am trying to create vertical content slider using jQuery, I have tried creating but its not working. I am trying to change the slide on scroll, any navigation is not required, only the content have to changed on scroll.
Here is the JSfiddle of my code
function rotateImages(){
$(".slide-item").animate({top: "-100%"}, 1000).delay(4000);
$(".slide-item").animate({top: "200%"}, 1000).delay(4000);
}
$(".slider-wrapper").scroll(function() {
rotateImages();
});
.slider-wrapper {
float: left;
width: 100%;
height: 500px;
background: #dedede;
border: 1px solid #ccc;
overflow: hidden;
position: relative;
}
.slide-item {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.item-one {
top: 0;
}
.item-two {
top: 100%
}
.slide-item > .img-block {
float: left;
width: 30%;
}
.slide-item > .img-block > img {
width: 100%;
height: auto;
}
.slide-item > .content-block {
float: right;
width: 70%;
padding: 0 20px;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="slider-wrapper">
<div class="slide-item item-one">
<div class="img-block"><img src="https://camo.mybb.com/e01de90be6012adc1b1701dba899491a9348ae79/687474703a2f2f7777772e6a71756572797363726970742e6e65742f696d616765732f53696d706c6573742d526573706f6e736976652d6a51756572792d496d6167652d4c69676874626f782d506c7567696e2d73696d706c652d6c69676874626f782e6a7067"></div>
<div class="content-block">
<h1>Slider Heading 1</h1>
<p>This is content related to slider. This is content related to slider. This is content related to slider. This is content related to slider. </p>
</div>
</div>
<div class="slide-item item-two">
<div class="img-block"><img src="https://camo.mybb.com/e01de90be6012adc1b1701dba899491a9348ae79/687474703a2f2f7777772e6a71756572797363726970742e6e65742f696d616765732f53696d706c6573742d526573706f6e736976652d6a51756572792d496d6167652d4c69676874626f782d506c7567696e2d73696d706c652d6c69676874626f782e6a7067"></div>
<div class="content-block">
<h1>Slider Heading 1</h1>
<p>This is content related to slider. This is content related to slider. This is content related to slider. This is content related to slider. </p>
</div>
</div>
</div>
I would suggest using jquery-mousewheel because scroll event won't work until and unless there is scrollbar.
Fiddle demo
$('.slider-wrapper').on('mousewheel', function(event) {
console.log(event.deltaX, event.deltaY, event.deltaFactor);
rotateImages();
});

Sliding div off-screen

I’m having a little trouble with this template: basically, I’m trying to add functionality where if you click a box it will expand sliding the other ones off-screen, but instead sliding the div off-screen it’s disappearing completely.
Here is what I have so far: JSFiddle.
$(function() {
$(".box").click(function() {
var isopened = $(this).attr("isopen");
if (isopened == "true") {
$(this).css("position", "relative").css("width", $(this).attr("data-ow"));
$(this).attr("isopen", "false");
}
else {
$(this).attr("data-ow", $(this).css("width"));
$(this).css("position", "relative").css("width", "40%");
$(this).attr("isopen", "true");
}
});
});
* {
margin: 0;
padding: 0;
}
.container {
width: 100%;
max-width: 100%;
max-height: 600px;
overflow: hidden;
}
.box {
height: 600px;
display: block;
width: 13.33333333%;
border: 1px solid white;
background-color: black;
float: right;
position: relative;
}
.box:first-of-type {
width: 29.0%;
background-color: orange;
}
.box:last-of-type {
width: 29.0%;
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
What I ultimately want is when one of the boxes is clicked it expands and instead of the entire div being hidden only the part which is off-screen is hidden:
I think you might like this flexbox solution as you can do what you want without usign any jQuery/JS. Pure CSS and HTML:
body {
background-color: black
}
#container {
display: flex;
width: 100%;
height: 50vh;
}
#container > div {
flex: 1;
min-width: 0;
transition:min-width 0.2s ease;
outline:0;
}
#container > div:focus {
min-width: 50vw;
}
<div id="container">
<div tabindex="0" style="background-color:blue"></div>
<div tabindex="0" style="background-color:orange"></div>
<div tabindex="0" style="background-color:green"></div>
<div tabindex="0" style="background-color:white"></div>
<div tabindex="0" style="background-color:blue"></div>
</div>
I used tabindex to give me the ability to use the :focus selector.

Categories