I have few draggable elements inside Scrollbar (mcustomscrollbar). If I try to drag this element to the droppable area which is below the visible area of scroller, then the scroll does not automatically move downwards.
Please suggest how this can be achieved.
In my case I use the mCustomScrollbar with jquery-sortable (https://johnny.github.io/jquery-sortable/) -
I needed a way to move the scroller content while dragging the sortable element to get to some hidden below content.
I used the onDrag event of jquery-sortable to move the scroller using mCustomScrollbar scrollTo method:
onDrag: function ($item, position) {
// original functionality - better be safe
$item.css(position);
var sign = '-';
if ($this._prevDragPositionY > position.top) {
sign = '+'; //console.log('scrolling up');
} else { //console.log('scrolling down'); }
$this._prevDragPositionY = position.top;
$('.jsScroll').mCustomScrollbar("scrollTo", sign + "=75", {
scrollInertia: 300,
scrollEasing: "linear"
});
I hope this helps :)
Related
Issue right now: https://www.loom.com/share/c2567ccbd8e44ab49d1138e65ae77973
I have a section or div in the middle of the page. On every scroll, I need to detect if I entered that div after scrolling from outside that div (either up scroll or down scroll) or I am just scrolling inside that div?
I will explain what I am trying to achieve
This is the site https://dev.plusplus.co/events/
For this section https://prnt.sc/25nbxzq
What I am trying to achieve is when I start scrolling from the top of the page, and after I enter that above section, the section locks and there is a slick slider inside that div and after the section locks, I need to change slides on up and down scroll.
But What is happening right now is especially in firefox browser, If I scroll from the top and enter that div, the slider automatically changes to second. I need to lock the scroll first which works and when I enter that section and scroll and then only change slide to second on next scroll
Code I am using right now.
// debounce from underscore.js
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
// use x and y mousewheel event data to navigate flickity
function slick_handle_wheel_event(e, slick_instance, slick_is_animating) {
// do not trigger a slide change if another is being animated
if (!slick_is_animating) {
// pick the larger of the two delta magnitudes (x or y) to determine nav direction
var direction =
Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;
console.log("wheel scroll ", e.deltaX, e.deltaY, direction);
if (direction > 0) {
// next slide
slick_instance.slick("slickNext");
} else {
// prev slide
slick_instance.slick("slickPrev");
}
}
}
// debounce the wheel event handling since trackpads can have a lot of inertia
var slick_handle_wheel_event_debounced = debounce(
slick_handle_wheel_event
, 80, true
);
// slider #2
const slick_3 = $("#firstscrollsection .content-left");
slick_3.not('.slick-initialized').slick({
dots: false,
vertical: true,
speed: 400,
fade: true,
waitForAnimate: false,
verticalSwiping: true,
slidesToShow: 1,
arrows: false,
infinite: false,
});
var slick_3_is_animating = false;
slick_3.on("afterChange", function(index) {
console.log("Slide after change " + index);
slick_3_is_animating = false;
});
slick_3.on("beforeChange", function(index) {
console.log("Slide before change " + index);
slick_3_is_animating = true;
});
$("#firstscrollsection .section-wrapper-animated").on("wheel", function(e) {
slick_handle_wheel_event_debounced(e.originalEvent, slick_3, slick_3_is_animating);
});
Assuming you're trying to create a parallax effect, I believe you're going about it the wrong way.
I'm also curious about these lines of code:
// pick the larger of the two delta magnitudes (x or y) to determine nav direction
var direction = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY;
console.log("wheel scroll ", e.deltaX, e.deltaY, direction);
Is there a reason for comparing deltaY with deltaX? As I understand that you're calculating scroll direction on the vertical axis.
MDN Web Docs outlines the following — maybe this could be the source of the issue with Firefox:
Note: Don't confuse the wheel event with the scroll event. The default action of a wheel event is implementation-specific, and doesn't necessarily dispatch a scroll event. Even when it does, the delta* values in the wheel event don't necessarily reflect the content's scrolling direction. Therefore, do not rely on the wheel event's delta* properties to get the scrolling direction. Instead, detect value changes of scrollLeft and scrollTop of the target in the scroll event.
If the pointer isn't directly hovering over the section, its wheel event won't fire. Also, the wheel event won't consider touch or scrollbar events. It's a better idea, in my opinion, to instead listen for the scroll event on the documentElement.
Here is my suggestion for changing the slide on the next scroll. You can detect if the scrollTop of the document meets your target element's(section in this case) offsetTop, then you will start calculating scroll direction before navigating the slider.
I'm trying to get element position while scrolling in a horizontal web page. I tried to use
main scrolling:
$('html, body, *').mousewheel(function(e, delta) {
this.scrollLeft -= (delta*60);
});
then:
$(window).scroll(function() {
alert('Anything');
});
But that doesn't work at all. I tried using mousewheel plugin
$('.internal.th').on('mousewheel',function(event) {
console.log(event.deltaX, event.deltaY, event.deltaFactor);
});
But it keeps displaying the same position -0 -1 100 no matter how much i scroll
I tried
$('.internal.th').on('scroll', function() {
var val = $(this).scrollLeft()
if (val >= 100) alert('Hello')
})
but it doesn't do anything at all
The idea is getting some item position from the left related to the window to manage another element rotation so I want to keep tracking the main item positing while scrolling horizontally not vertically
jQuery provides APIs
offset
position
you can use those
Below is a sample with both vertical and horizontal scrollbars
$(document).ready(function(){
document.addEventListener('scroll', function (event) {
console.log(event.target);
console.log($("#p3").position());
console.log($("#p3").offset());
console.log($("#p3").position().top - $("body").scrollTop());
console.log($("#p3").position().left - $("body").scrollLeft());
}, true);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>dasdasd</p>
<p>dasdasd</p>
<p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p>
<p style="width: 2500px;display:inline-block">dasdasd<div ></div></p>
<p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p id="p3">dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p><p>dasdasd</p>
Important: position and offset is relative to parent tag's position and offset
Having a bit of a problem. Looking to build a sticky nav, and when the sticky nav triggers, adding the 'is-sticky' class, i'd like to add a different class to another div.
Below is the code..
Thanks
<script>
$(document).ready(function(){
if ( $(".sticky-wrapper").hasClass("is-sticky") ) {
$("#menu-item-25").css({display: "inline"});
}
});
</script>
There's a lot going on here that I'm not sure about, but:
You need an event listener that leads to code that adds/removes the classes/css that you want. What you have now is an event listener, but it's listening for the document ready state, not a scroll that triggers a sticky nav. So:
<script>
$(document).ready(function(){
//add a listener for something that would indicate a sticky-state change, presumably scrolling
$(document).on('scroll', function() {
checkForStickyNav();
});
function checkForStickyNav() {
//look for sticky nav, and prevent running over and over
if ( $(".sticky-wrapper").hasClass("is-sticky") && !$(".otherStuff").hasClass("stickyfied") {
//do your stuff here; presumably changing CSS as appropriate
//make sure to add something along the lines of 'stickyfied' above, so that you don't keep re-adding the css on every scroll event
$("#menu-item-25").css({display: "inline"});
$('.otherStuff').addClass('stickyfied');
}
</script>
To add a class you need
$("#element").addClass('myclass');
You can also remove a class with
$("#element").removeClass('myclass');
And toggle a class with
$("#element").toggleClass('myclass');
But your code is far away from a sticky nav, here is how I do it
$(function() {
// grab the initial top offset of the navigation
var sticky_navigation_offset_top = $('nav').offset().top;
// our function that decides weather the navigation bar should have "fixed" css position or not.
var sticky_navigation = function(){
var scroll_top = $(window).scrollTop(); // our current vertical position from the top
// if we've scrolled more than the navigation, change its position to fixed to stick to top,
// otherwise change it back to relative
if (scroll_top > sticky_navigation_offset_top) {
$('nav').css({ 'position': 'fixed', 'top': '0px', 'left': '0px', 'line-height': '30px' });
} else {
$('nav').css({ 'position': 'relative', 'top': '0px' });
}
};
// run our function on load
sticky_navigation();
// and run it again every time you scroll
$(window).scroll(function() {
sticky_navigation();
});
});
Obviously you'll have to play around with the css
I have a series of buttons of fixed height and width, those need to be draggable and droppable anywhere inside the parent div.
As per client request, I cannot use any external libraries, meh... I could have done this with jQuery in seconds but, I guess this is one of its drawbacks: you don't get to learn more basic stuff...
How would I go about doing it? A problem with this is that those buttons are inside a div that is also draggable so I need to be careful about positioning, I can only probably use relative.
Any ideas how I can go about doing it? Thanks in advance.
Peter-Paul Koch wrote an excellent how-to on drag and drop. I only remembered this 3/4 of the way through writing my own, so I wrapped that up in a fiddle.
function makeDraggable(draggable, container){
// In case you don't want to have a container
var container = container || window;
// So we know what to do on mouseup:
// At this point we're not sure the user wants to drag
var dragging = false;
// The movement listener and position modifier
function dragHandler(moveEvent){
moveEvent.preventDefault();
dragging = true;
// Ascertain where the mouse is
var coordinates = [
moveEvent.clientX,
moveEvent.clientY
];
// Style properties we need to apply to the element
var styleValues = {
position : 'absolute',
left : coordinates[0] + 'px',
top : coordinates[1] + 'px'
};
// Apply said styles
for(property in styleValues){
if(styleValues.hasOwnProperty(property)){
draggable.style[property] = styleValues[property];
}
}
}
function dropHandler(upEvent){
// Only interfere if we've had a drag event
if(dragging === true){
// We don't want the button click event to fire!
upEvent.preventDefault();
// We don't want to listen for drag and drop until this is clicked again
container.removeEventListener('mousemove', dragHandler, false);
draggable.removeEventListener('mouseup', dropHandler, false);
dragging = false;
}
}
// Where all the fun happens
draggable.addEventListener('mousedown', function dragListener(downEvent){
downEvent.preventDefault();
// The drag event
container.addEventListener('mousemove', dragHandler, false);
// The end of drag, if dragging occurred
draggable.addEventListener('mouseup', dropHandler, false);
}, false);
}
I have picture of an arrow in a div. This div is fixed in the bottom right corner of very wide page.
How can I use jQuery to scroll the window right 600px each time the div is clicked? (And is it possible to detect when the page can no longer scroll right, and hide the arrow?)
Cheers.
Try something like this:
var distance = 600;
$("div").click(function() {
$("html:not(:animated), body:not(:animated)").animate(
{scrollLeft: "+="+distance}, 400
);
});
jsfiddle here: http://jsfiddle.net/juXLu/2/
[edit]
And here's detecting if you're at the end of the document http://jsfiddle.net/lukemartin/juXLu/5/
var distance = 600,
docWidth = $(document).width(),
scrollPos;
// click handler
$("div").click(function() {
// animate
$("html:not(:animated), body:not(:animated)").animate(
// amount to scroll
{scrollLeft: "+=" + distance},
// scroll speed (ms)
400,
// callback function
function(){
// check our scroll position
scrollPos = $(window).width() + $(window).scrollLeft();
// if it equals the doc width, we're at the end
if(docWidth === scrollPos) {
$("div").text("End of the line");
}
}
);
});
Use the jquery method scrollLeft
$(document).ready(function(){
$(window).scrollLeft((Number($(window).scrollLeft())+600)+'px');
});
Something like that :)
You could user the Scrollto plugin,
http://plugins.jquery.com/project/ScrollTo
It is really easy to use, just use the documentation. Then you could create a placeholder to determine whether or not its to the end of the page. Just stick the placeholder at the very end, and calculate the distance.