desandro / draggabilly

:point_down: Make that shiz draggable
https://draggabilly.desandro.com
MIT License
3.86k stars 386 forks source link

Scroll #1

Open desandro opened 11 years ago

desandro commented 11 years ago

When you drag an element close to the viewport's edge, it should scroll -- if enabled.

Add a 👍 reaction to this issue if you would like to see this feature added. Do not add +1 comments — They will be deleted.

jQuery UI Draggable has some nice options for this: scroll, scrollSensitivity, and scrollSpeed.

A possible awkward scenario involves when you have multiple dragging elements, one of the is ready to trigger scroll, but then another is at an opposite edge. Ideally the scroll should only be triggered while keeping every dragging element in the viewport.

woollsta commented 11 years ago

I imagine you would have to do something very roughly like this.. just written in crappy-tuesday-morning-pseudo-code.

declare global object inScrollArea;

for each draggable item {
    on drag move {
        if this drag pos is in scroll boundary {
              -> insert into inScrollArea[this index] value 1;
              -> if this index is the only value in array {
                       -> do scrolly stuff;
                  }else {
                       -> kill scrolly stuff;
                  }
        } else {
              -> remove inScrollArea[index];
        }
    }
    on drag end {
        -> remove inScrollArea[index];
    }
}

Of course it's bound to be more complicated because all active dragging elements will be triggering the scrolly script, so could cause some jittering and general usability hell.

Some things to consider I guess would include:

I haven't seen the jQuery UI's implementation, but I imagine they've come up with some clever. After using this with your packery library I can see this being a useful addition.

Also great job on the lot, I'm using packery and isotope in a project and getting extra brownie points from the manager. Wohay!

woollsta commented 11 years ago

Also interesting observation: IE8 appears to scroll the body automatically when dragging past the browser edge.

pistachiomatt commented 10 years ago

Hate to be a bumper, but this would be a great feature.

mbme commented 9 years ago

+1 for this feature

st-daristodemo commented 9 years ago

I agree, would be a great feature.

lkrids commented 9 years ago

+1

ctjhoa commented 9 years ago

+1

Nuru commented 9 years ago

+1 need this right now

EliotSlevin commented 8 years ago

+1

wswoodruff commented 8 years ago

+1

zacol commented 8 years ago

+1

Any idea how to do that?

sirgallifrey commented 8 years ago

I've made a fork from draggabilly that implements scrolling inside another element, autoscrolling and scalling (that I needed for a project). It's not perferct and it won't account for multiple dragging elements yet, but you guys can help me to improve :)

https://github.com/sirgallifrey/draggabilly-ps

jrdn91 commented 8 years ago

Any progress on this? I'm about to have to build my own implementation of it for our project using packery with draggabilly

chrisgrovers commented 8 years ago

^^ Any update @Jordan4jc? I'm about to do the same

jrdn91 commented 8 years ago

@chrisgrovers no, I haven't done anything with it yet, but I'll have to here soon.

jim-at-miramontes commented 6 years ago

Bump -- has there been, or is there likely to be, any progress on this? Just checking...

DataTables commented 4 years ago

If anyone else is interested in this, I've implemented as a couple of function calls to be called in dragStart (_startStopScroll) and dragEnd (_stopScroll).

Its TypeScript code and its offered as public domain - do as you will with it.

    private _pageYPosition: number;
    private _scrollTimer;

    private _startStopScroll(e: MouseEvent = null) {
        if (e) {
            this._pageYPosition = e.pageY;
        }

        if (this._pageYPosition > window.innerHeight + window.scrollY - 50) {
            if (! this._scrollTimer) {
                this._scrollTimer = setTimeout(() => {
                    window.scrollBy(0, 5);

                    this._pageYPosition += 5;
                    this._scrollTimer = null;
                    this._startStopScroll();
                }, 25);
            }
        }
        else if (this._pageYPosition < window.scrollY + 50) {
            if (! this._scrollTimer) {
                this._scrollTimer = setTimeout(() => {
                    window.scrollBy(0, -5);

                    this._pageYPosition -= 5;
                    this._scrollTimer = null;
                    this._startStopScroll();
                }, 25);
            }
        }
        else {
            if (this._scrollTimer) {
                clearTimeout(this._scrollTimer);
                this._scrollTimer = null;
            }
        }
    }

    private _stopScroll() {
        clearTimeout(this._scrollTimer);
        this._scrollTimer = null;
    }