javascript - DragOver and DragLeave in AngularJS -
i'm trying create element users can hold mouse on scroll page down while dragging element. necessary support drag-&-drop editor.
i'm detecting if user hovers on anchor , dragging, , if start $interval
initiate slow scroll. if mouse leave anchor, or user stops dragging, slow scroll should cancelled, it's not. below code.
elem.on('dragover', mouseover); elem.on('dragleave', mouseleave); elem.on('dragend', mouseleave); var scroller = null; function mouseover(ev) { ev.preventdefault(); console.log('over'); scroller = $interval(function () { if (!scrolledtobottom()) { $(window).scrolltop($(window).scrolltop() + 1); } }, 10); } function mouseleave(ev) { ev.preventdefault(); console.log('left'); $interval.cancel(scroller); scroller = null; } function scrolledtobottom() { return ($(window).scrolltop() + $(window).height()) == $(document).height(); }
even though console.log
's fire fine, scroller never stops scrolling. think because angular cannot see inside event it's triggered , fails apply changes scroller. however, angular has no ngdragover
, , can think of jquery implementations.
any suggestions?
the problem code have registered events elem.on('dragover', mouseover)
, elem.on('dragleave', mouseleave)
and elem.on('dragend', mouseleave)
, doc mentions during operations, several event types fired , event types might fired many times (for example drag , dragover event types).
for example dragover
event handler looks like:
function mouseover(ev) { ev.preventdefault(); console.log('over'); scroller = $interval(function () { if (!scrolledtobottom()) { $(window).scrolltop($(window).scrolltop() + 1); } }, 10); }
so, above event handler fire multiple times registering $interval
multiple time , loose reference old promise.
fix using following check:
var scroller = null; function mouseover(ev) { ev.preventdefault(); console.log('over'); if (scroller === null) { // <-- check prevent multiple $interval registration. scroller = $interval(function () { if (!scrolledtobottom()) { $(window).scrolltop($(window).scrolltop() + 1); } }, 10); } }
i remove elem.on('dragleave', mouseleave)
event handler registration call event handler if registered called start element drag. , cancelling custom scoll
logic.
also, suggest changing dragend
event handler make check before cancelling $interval
, like(this code clarity):
function mouseleave(ev) { ev.preventdefault(); if (scroller !== null) { // <-- make check before cancelling $interval.cancel(scroller); scroller = null; } }
here working example try out:
angular.module('myapp', []) .directive('drag', function($interval) { return { restrict: 'a', link: function(scope, elem, attrs, ctrl) { elem.on('dragover', mouseover); elem.on('dragend', mouseleave); var scroller = null; function mouseover(ev) { ev.preventdefault(); if (scroller === null) { scroller = $interval(function() { if (!scrolledtobottom()) { $(window).scrolltop($(window).scrolltop() + 1); } }, 10); } } function mouseleave(ev) { ev.preventdefault(); if (scroller !== null) { $interval.cancel(scroller); scroller = null; } } function scrolledtobottom() { return ($(window).scrolltop() + $(window).height()) == $(document).height(); } } } });
.container { padding: 0; margin: 0; background: blue; height: 800px; } .container .drag { height: 300px; } .container .drag { color: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js "></script> <div ng-app="myapp"> <div class="container"> <div class="drag"> <a href="" drag>drag me</a> </div> </div> </div>
Comments
Post a Comment