Skip to content

Commit

Permalink
fix(scrollView): stop memory-leak when destroying scrollView
Browse files Browse the repository at this point in the history
Fixes #1096
  • Loading branch information
ajoslin committed May 19, 2014
1 parent 6b402c3 commit 4a21013
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
1 change: 1 addition & 0 deletions js/angular/controller/scrollController.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $loca

$scope.$on('$destroy', function() {
deregisterInstance();
scrollView.__removeEventHandlers();
ionic.off('resize', resize, $window);
$window.removeEventListener('resize', resize);
backListenDone();
Expand Down
11 changes: 11 additions & 0 deletions js/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,17 @@
return null;
},

elementHasParent: function(element, parent) {
var current = element;
while (current) {
if (current.parentNode === parent) {
return true;
}
current = current.parentNode;
}
return false;
},

/**
* @ngdoc method
* @name ionic.DomUtil#rectContains
Expand Down
72 changes: 49 additions & 23 deletions js/views/scrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ ionic.views.Scroll = ionic.views.View.inherit({

scrollBottomOffsetToTop = container.getBoundingClientRect().bottom;
//distance from top of focused element to the bottom of the scroll view
var elementTopOffsetToScrollBottom = e.detail.elementTop - scrollBottomOffsetToTop;
var elementTopOffsetToScrollBottom = e.detail.elementTop - scrollBottomOffsetToTop;

var scrollTop = elementTopOffsetToScrollBottom + scrollMidpointOffset;
ionic.tap.cloneFocusedInput(container, self);
Expand Down Expand Up @@ -807,55 +807,82 @@ ionic.views.Scroll = ionic.views.View.inherit({
// Mouse Events
var mousedown = false;

container.addEventListener("mousedown", function(e) {
self.mouseDown = function(e) {
if ( ionic.tap.ignoreScrollStart(e) || e.target.tagName === 'SELECT' ) {
return;
}
self.doTouchStart(getEventTouches(e), e.timeStamp);

e.preventDefault();
mousedown = true;
}, false);
};

document.addEventListener("mousemove", function(e) {
self.mouseMove = function(e) {
if (!mousedown || e.defaultPrevented) {
return;
}

self.doTouchMove(getEventTouches(e), e.timeStamp);

mousedown = true;
}, false);
};

document.addEventListener("mouseup", function(e) {
self.mouseUp = function(e) {
if (!mousedown) {
return;
}

self.doTouchEnd(e.timeStamp);

mousedown = false;
}, false);

var wheelShowBarFn = ionic.debounce(function() {
self.__fadeScrollbars('in');
}, 500, true);
};

var wheelHideBarFn = ionic.debounce(function() {
self.__fadeScrollbars('out');
}, 100, false);
self.mouseWheel = ionic.animationFrameThrottle(function(e) {
if (ionic.DomUtil.elementHasParent(e.target, self.__container)) {
self.hintResize();
self.scrollBy(
e.wheelDeltaX/self.options.wheelDampen,
-e.wheelDeltaY/self.options.wheelDampen
);
self.__fadeScrollbars('in');
clearTimeout(self.__wheelHideBarTimeout);
self.__wheelHideBarTimeout = setTimeout(function() {
self.__fadeScrollbars('out');
}, 100);
}
});

//For Firefox
document.addEventListener('mousewheel', onMouseWheel);
}
function onMouseWheel(e) {
self.hintResize();
wheelShowBarFn();
self.scrollBy(e.wheelDeltaX/self.options.wheelDampen, -e.wheelDeltaY/self.options.wheelDampen);
wheelHideBarFn();
container.addEventListener("mousedown", self.mouseDown, false);
document.addEventListener("mousemove", self.mouseMove, false);
document.addEventListener("mouseup", self.mouseUp, false);
document.addEventListener('mousewheel', self.mouseWheel, false);
}
},

__removeEventHandlers: function() {
var container = this.__container;

container.removeEventListener('touchstart', self.touchStart);
document.removeEventListener('touchmove', self.touchMove);
document.removeEventListener('touchend', self.touchEnd);
document.removeEventListener('touchcancel', self.touchCancel);

container.removeEventListener("pointerdown", self.touchStart);
document.removeEventListener("pointermove", self.touchMove);
document.removeEventListener("pointerup", self.touchEnd);
document.removeEventListener("pointercancel", self.touchEnd);

container.removeEventListener("MSPointerDown", self.touchStart);
document.removeEventListener("MSPointerMove", self.touchMove);
document.removeEventListener("MSPointerUp", self.touchEnd);
document.removeEventListener("MSPointerCancel", self.touchEnd);

container.removeEventListener("mousedown", self.mouseDown);
document.removeEventListener("mousemove", self.mouseMove);
document.removeEventListener("mouseup", self.mouseUp);
document.removeEventListener('mousewheel', self.mouseWheel);
},

/** Create a scroll bar div with the given direction **/
__createScrollbar: function(direction) {
var bar = document.createElement('div'),
Expand Down Expand Up @@ -1503,7 +1530,6 @@ ionic.views.Scroll = ionic.views.View.inherit({

},


/**
* Touch start handler for scrolling support
*/
Expand Down

0 comments on commit 4a21013

Please sign in to comment.