Giter Club home page Giter Club logo

dom_autoscroller's Introduction

dom-autoscroller

dom autoscroller

The syncMove option and synchronizing move

dom-autoscroller has a new option named syncMove.

syncMove takes a boolean, or a function that returns a boolean, and the returned value of syncMove toggles the event synching of dom-autoscroller.

Why do that? There are some situations where dom-autoscroller might be doing what it does, but even though the mouse cursor moves relative to the scroll position mousemove events do not get fired. When you set syncMove to true that allows mousemove events with fresh coordinates to be fired for some other source that might need those events.

For now the option syncMove is set to false. This is for experimental purposes, and because this functionality is likely to be buggy. touchmove syncing is also planned, but it's best if the integration of move syncing be taken slow. Please leave plenty of issues to help integrate syncMove, and mousemove dispatch into dom-autoscroller.

Once movement sync is fully integrated into dom-autoscroller the syncMove option might be set to default true, or removed entirely. It depends on how things work out down the line.

Big Announcement!

Version 2 of dom-autoscroller is out. You can upgrade to version 2.

Here are the differences.

  • pixels option removed.
  • maxSpeed option added.
  • Slightly different algorithm for scrolling
  • Scrolling speed changes dynamically based on distance from element edge
  • Compatibility with rollup.

Scrolling in dom-autoscroller is now much smoother. So you should upgrade to version 2.

Install

NPM

npm install --save dom-autoscroller

BOWER

bower install --save dom-autoscroller

Then use browserify, webpack, or rollup to build your script.

Or Download one of these files from the Github repo:

  • dist/dom-autoscroller.js
  • dist/dom-autoscroller.min.js

If you use one of these prepackaged files the global name is autoScroll.

Demo

jsfiddle Demo of dom-autoscroller

Usage

This example uses link-css, and dragula.

require('link-css')('../node_modules/dragula/dist/dragula.min.css');
var dragula = require('dragula'),
    autoScroll = require('dom-autoscroller');


var drake = dragula([document.querySelector('#list'), document.querySelector('#hlist')]);
var scroll = autoScroll([
        document.querySelector('#list-container'),
        document.querySelector('#container2')
    ],{
    margin: 20,
    maxSpeed: 5,
    scrollWhenOutside: true,
    autoScroll: function(){
        //Only scroll when the pointer is down, and there is a child being dragged.
        return this.down && drake.dragging;
    }
});

Keep In Mind

dom-autoscroller exploits the simplicity of the single parent, to child relationship. A scrolling element with more than one children will likely not work well with dom-autoscroller.

For clarity here is a more complete example:

<!DOCTYPE html>
<html>
<head>
    <title>Drag test</title>
    <style>
    #list-container{
        /*The height produces the scroll bar.*/
        height: 100px;
        /*Make this scrollable.*/
        overflow-y: auto;
    }
    </style>
</head>
<body>
    <div id="list-container">
        <ol id="list" type="1">
            <li>zero</li>
            <li>one</li>
            <li>two</li>
            <li>three</li>
            <li>four</li>
            <li>five</li>
            <li>six</li>
            <li>seven</li>
            <li>eight</li>
            <li>nine</li>
            <li>ten</li>
            <li>eleven</li>
            <li>twelve</li>
            <li>thirteen</li>
            <li>fourteen</li>
            <li>fifteen</li>
        </ol>
    </div>
    <div id="container2">
        <ol id="hlist">
            <li>zero</li>
            <li>one</li>
            <li>two</li>
            <li>three</li>
            <li>four</li>
            <li>five</li>
            <li>six</li>
            <li>seven</li>
            <li>eight</li>
            <li>nine</li>
            <li>ten</li>
            <li>11</li>
            <li>12</li>
            <li>13</li>
            <li>14</li>
            <li>15</li>
        </ol>
    </div>
    <script>
    //Load dragula's css.
    require('link-css')('../node_modules/dragula/dist/dragula.min.css');
    var dragula = require('dragula'),
        papyri = require('dom-autoscroller');


    var drake = dragula([document.querySelector('#list'), document.querySelector('#hlist')]);
    var scroll = autoScroll([
            document.querySelector('#list-container'),
            document.querySelector('#container2')
        ],{
        margin: 20,
        pixels: 5,
        scrollWhenOutside: false,
        autoScroll: function(){
            return this.down && drake.dragging;
        }
    });
    </script>
</body>
</html>

If you look at the last example notice the containers have only one child, and that they're different from the containers used by dragula. In theory multiple children could work with dom-autoscroller, but the children scrolling might interfere with the workings of the library dragula.

Auto Scroller API

autoScroll(element|elements, options) -> instance

Create an auto scroller on an element, or and array of elements.

The element should have only one child element to work consistently.

options.margin = Integer

An inner area to detect when the pointer is close to the edge.

options.autoScroll = Function

A callback function used to determine if the element should scroll, or when the element should scroll.

Return a boolean value from this function to allow scrolling.

options.maxSpeed = Integer

maxSpeed defaults to 4.

Speed effects in dom-autoscroller:

  1. Speed adjusts dynamically depending on how close to the edge your pointer is.
  2. Speed is pixels per frame.

maxSpeed limits pixels per frame.

options.pixels = Integer

removed in version 2

Set how many pixels per second you want to scroll during the auto scrolling action. More is smoother.

Speed was pixels/second in version 1, and in version 2 speed is pixels/frame.

options.scrollWhenOutside = Boolean

Whther or not it should continue to scroll when the pointer is outside the container. Defaults to false.

Auto Scroller Properties

down = Boolean

Is the pointer down?

scrolling = Boolean

Is one of the elements scrolling?

point = Object

This reference no longer exists.

A reference to the pointer object.

Auto Scroller Methods

autoScroll

The function you set in the constructor options for options.autoScroll.

destroy(forceCleanAnimation)

Remove all event listeners needed to be able to track the pointer. If destroy Auto Scroller meanwhile scrolling then just call .destroy(true) to force to stop scrolling animation. Call .destroy() and .destroy(false) is the same behaviours.

Undocumented methods

There are undocumented methods in version 2.

These are:

  1. add()
  2. remove()

These methods add, or remove elements from dom-autoscroller.

Why are these considered undocumented even though there here in the document? :)

add, and remove are incomplete, and there is no detailed explanation. Use these methods at your own risk.

About

There are tons of reasons to have auto scrolling. The main one being sometimes a finger can't reach the mouse wheel comfortably. dom-autoscroller is a comfort module.

This is also a nice small module to do this kind of thing when auto scrolling is all you need.

dom_autoscroller's People

Contributors

chrisjlee avatar cinaglia avatar germainbergeron avatar hollowdoor avatar ivancoronado avatar sangcu avatar zuzana avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

dom_autoscroller's Issues

autoScroll starts scrolling when modification is done via chrome dev tools

I am using dom-autoscroller with my Angular (v5) project and it works fine for the intended purpose. However i have noticed that when ever i modify something from the chrome dev tools to the elements of the applied scroller (such as changing class names or removing a DOM element) - it triggers the autoscroll to scroll all the way up unless i go to my browser window and click init.
I am not sure why its triggering, probably a bug ?

For reference this is my autoscroller code:

this.autoscroller = autoScroll([this.rightPanel.nativeElement],{
	margin: 20,
	maxSpeed: 15,
	scrollWhenOutside: true,
	autoScroll: function() {
		return this.down;
	}
});

Where rightPanel is the element i have applied the autoscroller to.

Performance problem

I have performance problems with dom_autoscroller. I use Angular and Ngx-dnd. No worries for several years with these technologies no matter how many items are displayed. Nevertheless we wanted to add the possibility of being able to scroll while dragging and dropping. The addition of dom_autoscroller has been a concern but problems of slowness are immediately felt. The slightest movement of an element is very slow.

Any ideas?

Bundle for browsers

Thanks for the lib, it solve a problem that I have with dragula 😄

I only have a small problem with the library, it uses a require which is not supported by my browser so I can't include the script directly. Could you add a bundled file in a dist folder?

Bower version

Since you can't version your project with bower version (bower spec).
Can you please create a tag with last version so we can install it with bower install dom-autoscroller#2.2.6 --save?
Thanks in advance.

Build files in dist folder are not working

getClientRect function throws an exception in dependecy 'dom-plane', makes dist build files unusable.

Always throws exception when DOM element is provided, because of rext.x typo. (should be rect.x).

image

Trigger mousemove events while scrolling

Objects being dragged generally only update on mousemove, and thus lag behind when autoscrolling, unless the object is isolated from the scroll offset of the container (as apparently is the case in dragula).
For example if using jquery.nestable as in this jsfiddle, the dragged element doesn't update while scrolling unless you continuously move the mouse.

dom-autoscroller should trigger mousemove events while scrolling to make these applications work seamlessly without additional code. It'll have to avoid retriggering itself from the events (which should be fairly easy), and should probably avoid sending extra mousemove events when the mouse is already moving, but hopefully in a way that keeps it smooth (i.e. only avoid triggering the event if a mousemove was received since the last animation frame, rather than since some fixed amount of time)

Chrome for mac doesn't seem to like +/- 1px scrollTo

Thanks for the handy library. I'm using it in conjunction with Dragula.

I was having some issues getting it to work with the target element as window (also with other configurations), and I decided to go check it in Safari. It worked. But not in Chrome. (Version 51.0.2704.29 beta (64-bit) for Mac).

Perplexed I dropped in breakpoints and saw that the window.pageYOffset was never incrementing. Somehow, surprisingly, it does increment if the base increment in on('move') is 3px or more.

My caller (I reduced pixels from my desired speed to compensate for the increased increment in move):

      autoScroll([window],
        margin: 30,
        pixels: 50,
        scrollWhenOutside: true,
        autoScroll: function() { return this.down; })

My adjustment to your library.

    this.point.on('move', function(el, rect){

        if(!el) return;
        if(!self.autoScroll()) return;
        if(!self.scrollWhenOutside && this.outside(el)) return;

        if(self.point.y < rect.top + self.margin){
            autoScrollV(el, -3, rect);
        }else if(self.point.y > rect.bottom - self.margin){
            autoScrollV(el, 3, rect);
        }

        if(self.point.x < rect.left + self.margin){
            autoScrollH(el, -3, rect);
        }else if(self.point.x > rect.right - self.margin){
            autoScrollH(el, 3, rect);
        }
    });

I'm on a non-retina Mac, so I don't expect any weird effects from pixel size, but my front-end fu is a little weak. Curious if anyone else has seen this and if it is worth digging into more.

onDestroy should stop auto scroll immediately.

There is the case when a user drags an item, then, press ESC to cancel drag event. In this case, we should stop auto-scroll immediately in destroy method instead of waiting for mouseup event to be dispatched.
@hollowdoor: what do you think about this?

Live demo please

Is there a live demo somewhere, so I can see it in action quickly? Thanks

License?

Is this MIT licensed? If so i can provide a pull request to add the license.

And also, is it possible to get this repository tagged with versions?

Kanban.js drag an entire list div horizontally to a position off-screen

Dragging specific items from a list div works, drag an entire list div horizontally off-screen?

Question:

Is there a way to drag an entire list div horizontally to a position off-screen?

example:

  • I have 5 list divs in a container div
  • 3 list divs are showing on-screen with items
  • I want to drag the first list div to the final end position horizontally currently off-screen

Thanks! And for a great kit.

Scrolling speed behavior

Currently the scrolling speed increases based on the number of mousemove events in the scroll area, apparently because it accumulates many setTimeouts.

Instead the speed should be based on the distance to the edge within the margin. This is what browsers, operating systems etc. do because it lets the user control the speed in a meaningful way.

After checking out this library's demo, I've implemented the desired behavior in my audio editor Wavey.
Here's the relevant code extracted (and modified a bit) (in CoffeeScript):

auto_scroll_margin = 30
auto_scroll_max_speed = 20

auto_scroll_container_el.addEventListener "mousedown", (e)->

    auto_scroll_container_rect = auto_scroll_container_el.getBoundingClientRect()
    auto_scroll_rect =
        left: auto_scroll_container_rect.left
        top: auto_scroll_container_rect.top
        width: auto_scroll_container_el.clientWidth
        height: auto_scroll_container_el.clientHeight
        right: auto_scroll_container_rect.left + auto_scroll_container_el.clientWidth
        bottom: auto_scroll_container_rect.top + auto_scroll_container_el.clientHeight

    mouse_x = 0
    mouse_y = 0
    auto_scroll_x = 0
    auto_scroll_y = 0
    auto_scroll_animation_frame = -1

    auto_scroll = ->
        auto_scroll_x =
            if mouse_x < auto_scroll_rect.left + auto_scroll_margin
                Math.max(-1, (mouse_x - auto_scroll_rect.left) / auto_scroll_margin - 1) * auto_scroll_max_speed
            else if mouse_x > auto_scroll_rect.right - auto_scroll_margin
                Math.min(1, (mouse_x - auto_scroll_rect.right) / auto_scroll_margin + 1) * auto_scroll_max_speed
            else
                0

        auto_scroll_y =
            if mouse_y < auto_scroll_rect.top + auto_scroll_margin
                Math.max(-1, (mouse_y - auto_scroll_rect.top) / auto_scroll_margin - 1) * auto_scroll_max_speed
            else if mouse_y > auto_scroll_rect.bottom - auto_scroll_margin
                Math.min(1, (mouse_y - auto_scroll_rect.bottom) / auto_scroll_margin + 1) * auto_scroll_max_speed
            else
                0

        # <update selection while scrolling here>

        setTimeout ->
            auto_scroll_container_el.scrollLeft += auto_scroll_x
            auto_scroll_container_el.scrollTop += auto_scroll_y

        auto_scroll_animation_frame = requestAnimationFrame(auto_scroll)

    window.addEventListener "mousemove", onMouseMove = (e)->
        mouse_x = e.clientX
        mouse_y = e.clientY
        cancelAnimationFrame(auto_scroll_animation_frame)
        auto_scroll_animation_frame = requestAnimationFrame(auto_scroll)

    window.addEventListener "mouseup", onMouseUp = (e)->
        window.removeEventListener "mouseup", onMouseUp
        window.removeEventListener "mousemove", onMouseMove
        cancelAnimationFrame(auto_scroll_animation_frame)

Uncaught ReferenceError: autoScroll is not defined

Heya so I am working on a non-ES6 project right now and wanted to use this lib. I noticed that there is no bower package yet so I just installed via npm and piped the node_modules/dom-autoscroller/dist/dom-autoscroller.js into my gulpfile.

When I try to call the autoScroll method, I get the above error.

Version 3 plan

For future refinements, and enhancements in version 3 of dom-autoscroller.

Please use the dev3 branch for developing version 3 in your pull requests.

Put " -version 3" at the end of the title of issues when you:

  • Find bugs that would require a user land breaking fix in version 2
  • Are proposing a major enhancement (even if it's not breaking)
  • Want to work on version 3, and would like a way to track your work
  • Want your proposed enhancement added to the below todo list.
  • Want to forward a bug fix from version 2.

Todo

  • Create independent "safe" dev branch for version 3 (possibly named "dev3")
  • Add release notes file (remove release notes from readme).
  • Remove the boolean switch in the destroy method
    • This was a temporary measure for issue #24
  • Work on the syncMove method
    • Should it remain an option, or be a default?
    • Should syncMove be default true, or false?
    • How should syncMove work in the broader environments (touch, ...)

Multiple autoscrolling divs scrolled at once

I have two separate divs, for both I have separate autoscroller configuration. When I dragged only in one of them, the second isn't being scrolled. But if I start drag-scrolling in one and continue drag-scrolling in the second (so it is one single drag) both of them get scrolled.

Unexpected value 'undefined' imported by the module 'DynamicTestModule'

It breaks ng test
error properties: Object({ ngSyntaxError: true }) Error: Unexpected value 'undefined' imported by the module 'DynamicTestModule' at syntaxError (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:1021:1) at http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:10589:1 at <Jasmine> at CompileMetadataResolver.push../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:10558:1) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:23876:1) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndAllComponents (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:23864:1) at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAndAllComponentsAsync (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/compiler/fesm5/compiler.js:23823:1) at CompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAndAllComponentsAsync (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js:153:1) at TestingCompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/testing.js.TestingCompilerImpl.compileModuleAndAllComponentsAsync (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/platform-browser-dynamic/fesm5/testing.js:220:1) at TestBed.push../node_modules/@angular/core/fesm5/testing.js.TestBed.compileComponents (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm5/testing.js:945:1)

Auto-scroll while dragging a “draggable” element

I have a doc with a limited height (overflow scroll) and inside this I have a number of elements with the “draggable” attribute.

I’m trying to use this package to automatically scroll my soup and down but it seems that the mousemove-event is not fired while dragging in Firefox. Is this something that has been raised before? Would it be something that you would like to support? I would be happy to help out but wanted to raise an issue before.

Cheers!

UPS, just found this #42

So maybe just give that branch a spin.

Any reason it’s not merged or is this project not maintained?

Bower?

Would you mind creating a bower package for this lib?

Unexpected token export when used with Create-react-app

Hi! I'm trying to use this nice module, but for some reason this module is hitting a unexpected token export when I try to import the library (after a standard npm install) with:

import autoScroll from 'dom-autoscroller';

I found a way to make it work by moving the dom-autoscroller.js into my src and then referencing it with:
import autoScroll from './dom-autoscroller';

Just wanted to let you know and see if you're getting the same behavior.

How to reinitialise the autoScroll when a new element is added to the group?

How do we reinitialise the autoScroll for a new column that is dynamically added?
For example, consider we have Trello like board where there are two columns like "Todo" and "In progress". Consider we have already initialised the autoScroll for these two columns on load to inherit the autoscrolling property when we drag the cards around. Now i am adding a new column named "Done" dynamically without any page refresh. How do i reinitialise the autoScroll function on the 3rd column in this case. I have tried making a function like shown below whenever i add new columns and called it when i create new columns.

initScroll() { autoScroll([document.querySelector('.list-container')], { margin: 20, maxSpeed: 5, scrollWhenOutside: true, autoScroll: function(){ //Only scroll when the pointer is down, and there is a child being dragged. return this.down; } }); }

But this doesn't work and i see that dragging cards around after calling this function multiple times makes the app so slow, seems like some kind of recursive function calls is happening internally if the function initScroll() is made more than once without a page referesh. I would like to understand a workaround for this. Is this a bug?

delay before scroll

Would it be possible to add a delay time a mouse has to be idea before starting the auto scroll? I thought I might be able to do this with the autoScroll callback but didn't have any luck.

The interface I'm developing has a fixed list on the left and multiple columns in a scrollable area to the right. If I've scrolled that area to the right and then drag an item from my list on the left I don't want to trigger the scroll left action for the brief second the mouse moves over the hotspot for that action. It causes the scrollable area to scroll to the left slightly making the interface feel a bit jumpy as you drag items from the list.

Remove polyfills + embrace web standards

The polyfills should not be forced into the bundles, IMO - instead you should just document that if browsers need e.g. requestAnimationFrame, then they need to add X polyfills e.g with a service like
http://polyfill.io

Imagine if every library out there added their own polyfills for Promises, DOM operations, etc, it would cause a big unnecessary javascript bundle for modern browsers.

Also it would be great if this library needs to embrace web standards:

https://caniuse.com/#search=elementFromPoint
https://caniuse.com/#search=append
https://caniuse.com/#search=remove
https://caniuse.com/#search=requestanimationframe

This would massively decrease the bundle size, with only a small additional step to add the necessary polyfills for those who want to support older browsers. Just my two cents. 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.