diff --git a/js/angular/controller/navViewController.js b/js/angular/controller/navViewController.js
index 19aa5e4d739..4f8e647fa5a 100644
--- a/js/angular/controller/navViewController.js
+++ b/js/angular/controller/navViewController.js
@@ -45,7 +45,14 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
$element.data('$uiView', viewData);
var deregisterInstance = $ionicNavViewDelegate._registerInstance(self, $attrs.delegateHandle);
- $scope.$on('$destroy', deregisterInstance);
+ $scope.$on('$destroy', function() {
+ deregisterInstance();
+
+ // ensure no scrolls have been left frozen
+ if (self.isSwipeFreeze) {
+ $ionicScrollDelegate.freezeAllScrolls(false);
+ }
+ });
$scope.$on('$ionicHistory.deselect', self.cacheCleanup);
@@ -176,6 +183,11 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
}
navSwipeAttr('');
+
+ // ensure no scrolls have been left frozen
+ if (self.isSwipeFreeze) {
+ $ionicScrollDelegate.freezeAllScrolls(false);
+ }
};
@@ -303,7 +315,7 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
if (!windowWidth) windowWidth = window.innerWidth;
- freezeScrolls(true);
+ self.isSwipeFreeze = $ionicScrollDelegate.freezeAllScrolls(true);
var registerData = {
direction: 'back'
@@ -387,7 +399,7 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
windowWidth = viewTransition = dragPoints = null;
- freezeScrolls(false);
+ self.isSwipeFreeze = $ionicScrollDelegate.freezeAllScrolls(false);
}
function getDragX(ev) {
@@ -409,13 +421,6 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
};
- function freezeScrolls(freeze) {
- forEach($ionicScrollDelegate._instances, function(instance) {
- instance.freezeScroll(freeze);
- });
- }
-
-
function navSwipeAttr(val) {
ionic.DomUtil.cachedAttr($element, 'nav-swipe', val);
}
diff --git a/js/angular/controller/scrollController.js b/js/angular/controller/scrollController.js
index 60bd0592af5..b7d55a06640 100644
--- a/js/angular/controller/scrollController.js
+++ b/js/angular/controller/scrollController.js
@@ -158,9 +158,12 @@ function($scope,
});
};
- self.freezeScroll = function(shouldFreeze) {
- if (arguments.length) scrollView.options.freeze = shouldFreeze;
- return scrollView.options.freeze;
+ self.freezeScroll = scrollView.freeze;
+
+ self.freezeAllScrolls = function(shouldFreeze) {
+ for (var i = 0; i < $ionicScrollDelegate._instances.length; i++) {
+ $ionicScrollDelegate._instances[x].freezeScroll(shouldFreeze);
+ }
};
diff --git a/js/angular/directive/list.js b/js/angular/directive/list.js
index ca0a0752f9d..7b16027a019 100644
--- a/js/angular/directive/list.js
+++ b/js/angular/directive/list.js
@@ -91,15 +91,16 @@ function($timeout) {
controller: '$ionicList',
compile: function($element, $attr) {
var listEl = jqLite('
')
- .append( $element.contents() )
+ .append($element.contents())
.addClass($attr.type);
+
$element.append(listEl);
return function($scope, $element, $attrs, ctrls) {
var listCtrl = ctrls[0];
var scrollCtrl = ctrls[1];
- //Wait for child elements to render...
+ // Wait for child elements to render...
$timeout(init);
function init() {
@@ -111,9 +112,9 @@ function($timeout) {
onReorder: function(el, oldIndex, newIndex) {
var itemScope = jqLite(el).scope();
if (itemScope && itemScope.$onReorder) {
- //Make sure onReorder is called in apply cycle,
- //but also make sure it has no conflicts by doing
- //$evalAsync
+ // Make sure onReorder is called in apply cycle,
+ // but also make sure it has no conflicts by doing
+ // $evalAsync
$timeout(function() {
itemScope.$onReorder(oldIndex, newIndex);
});
@@ -125,7 +126,7 @@ function($timeout) {
});
$scope.$on('$destroy', function() {
- if(listView) {
+ if (listView) {
listView.deregister && listView.deregister();
listView = null;
}
diff --git a/js/angular/service/scrollDelegate.js b/js/angular/service/scrollDelegate.js
index f4f179a2f11..0dd64f1aab1 100644
--- a/js/angular/service/scrollDelegate.js
+++ b/js/angular/service/scrollDelegate.js
@@ -133,10 +133,18 @@ IonicModule
/**
* @ngdoc method
* @name $ionicScrollDelegate#freezeScroll
- * @description Does not allow the scrollView to scroll in either x or y.
+ * @description Does not allow this scroll view to scroll either x or y.
+ * @param {boolean=} shouldFreeze Should this scroll view be prevented from scrolling or not.
* @returns {object} If the scroll view is being prevented from scrolling or not.
*/
'freezeScroll',
+ /**
+ * @ngdoc method
+ * @name $ionicScrollDelegate#freezeAllScrolls
+ * @description Does not allow any of the app's scroll views to scroll either x or y.
+ * @param {boolean=} shouldFreeze Should all app scrolls be prevented from scrolling or not.
+ */
+ 'freezeAllScrolls',
/**
* @ngdoc method
* @name $ionicScrollDelegate#getScrollView
diff --git a/js/views/listView.js b/js/views/listView.js
index 0fb1294b8e1..655824ff9a5 100644
--- a/js/views/listView.js
+++ b/js/views/listView.js
@@ -141,25 +141,26 @@
});
SlideDrag.prototype.end = function(e, doneCallback) {
- var _this = this;
+ var self = this;
// There is no drag, just end immediately
- if (!this._currentDrag) {
+ if (!self._currentDrag) {
doneCallback && doneCallback();
return;
}
// If we are currently dragging, we want to snap back into place
// The final resting point X will be the width of the exposed buttons
- var restingPoint = -this._currentDrag.buttonsWidth;
+ var restingPoint = -self._currentDrag.buttonsWidth;
// Check if the drag didn't clear the buttons mid-point
// and we aren't moving fast enough to swipe open
- if (e.gesture.deltaX > -(this._currentDrag.buttonsWidth / 2)) {
+ if (e.gesture.deltaX > -(self._currentDrag.buttonsWidth / 2)) {
// If we are going left but too slow, or going right, go back to resting
if (e.gesture.direction == "left" && Math.abs(e.gesture.velocityX) < 0.3) {
restingPoint = 0;
+
} else if (e.gesture.direction == "right") {
restingPoint = 0;
}
@@ -168,27 +169,27 @@
ionic.requestAnimationFrame(function() {
if (restingPoint === 0) {
- _this._currentDrag.content.style[ionic.CSS.TRANSFORM] = '';
- var buttons = _this._currentDrag.buttons;
+ self._currentDrag.content.style[ionic.CSS.TRANSFORM] = '';
+ var buttons = self._currentDrag.buttons;
setTimeout(function() {
buttons && buttons.classList.add('invisible');
}, 250);
} else {
- _this._currentDrag.content.style[ionic.CSS.TRANSFORM] = 'translate3d(' + restingPoint + 'px, 0, 0)';
+ self._currentDrag.content.style[ionic.CSS.TRANSFORM] = 'translate3d(' + restingPoint + 'px,0,0)';
}
- _this._currentDrag.content.style[ionic.CSS.TRANSITION] = '';
+ self._currentDrag.content.style[ionic.CSS.TRANSITION] = '';
// Kill the current drag
- if (!_this._lastDrag) {
- _this._lastDrag = {};
+ if (!self._lastDrag) {
+ self._lastDrag = {};
}
- ionic.extend(_this._lastDrag, _this._currentDrag);
- if (_this._currentDrag) {
- _this._currentDrag.buttons = null;
- _this._currentDrag.content = null;
+ ionic.extend(self._lastDrag, self._currentDrag);
+ if (self._currentDrag) {
+ self._currentDrag.buttons = null;
+ self._currentDrag.content = null;
}
- _this._currentDrag = null;
+ self._currentDrag = null;
// We are done, notify caller
doneCallback && doneCallback();
@@ -196,18 +197,20 @@
};
var ReorderDrag = function(opts) {
- this.dragThresholdY = opts.dragThresholdY || 0;
- this.onReorder = opts.onReorder;
- this.listEl = opts.listEl;
- this.el = this.item = opts.el;
- this.scrollEl = opts.scrollEl;
- this.scrollView = opts.scrollView;
+ var self = this;
+
+ self.dragThresholdY = opts.dragThresholdY || 0;
+ self.onReorder = opts.onReorder;
+ self.listEl = opts.listEl;
+ self.el = self.item = opts.el;
+ self.scrollEl = opts.scrollEl;
+ self.scrollView = opts.scrollView;
// Get the True Top of the list el http://www.quirksmode.org/js/findpos.html
- this.listElTrueTop = 0;
- if (this.listEl.offsetParent) {
- var obj = this.listEl;
+ self.listElTrueTop = 0;
+ if (self.listEl.offsetParent) {
+ var obj = self.listEl;
do {
- this.listElTrueTop += obj.offsetTop;
+ self.listElTrueTop += obj.offsetTop;
obj = obj.offsetParent;
} while (obj);
}
@@ -224,10 +227,7 @@
};
ReorderDrag.prototype.deregister = function() {
- this.listEl = null;
- this.el = null;
- this.scrollEl = null;
- this.scrollView = null;
+ this.listEl = this.el = this.scrollEl = this.scrollView = null;
};
ReorderDrag.prototype.start = function(e) {
@@ -310,13 +310,14 @@
// When an item is dragged, we need to reorder any items for sorting purposes
ReorderDrag.prototype._getReorderIndex = function() {
var self = this;
- var placeholder = this._currentDrag.placeholder;
- var siblings = Array.prototype.slice.call(this._currentDrag.placeholder.parentNode.children)
+
+ var placeholder = self._currentDrag.placeholder;
+ var siblings = Array.prototype.slice.call(self._currentDrag.placeholder.parentNode.children)
.filter(function(el) {
return el.nodeName === self.el.nodeName && el !== self.el;
});
- var dragOffsetTop = this._currentDrag.currentY;
+ var dragOffsetTop = self._currentDrag.currentY;
var el;
for (var i = 0, len = siblings.length; i < len; i++) {
el = siblings[i];
@@ -333,7 +334,7 @@
return i;
}
}
- return this._currentDrag.startIndex;
+ return self._currentDrag.startIndex;
};
ReorderDrag.prototype.end = function(e, doneCallback) {
@@ -370,7 +371,7 @@
*/
ionic.views.ListView = ionic.views.View.inherit({
initialize: function(opts) {
- var _this = this;
+ var self = this;
opts = ionic.extend({
onReorder: function(el, oldIndex, newIndex) {},
@@ -381,37 +382,37 @@
}
}, opts);
- ionic.extend(this, opts);
+ ionic.extend(self, opts);
- if (!this.itemHeight && this.listEl) {
- this.itemHeight = this.listEl.children[0] && parseInt(this.listEl.children[0].style.height, 10);
+ if (!self.itemHeight && self.listEl) {
+ self.itemHeight = self.listEl.children[0] && parseInt(self.listEl.children[0].style.height, 10);
}
- //ionic.views.ListView.__super__.initialize.call(this, opts);
-
- this.onRefresh = opts.onRefresh || function() {};
- this.onRefreshOpening = opts.onRefreshOpening || function() {};
- this.onRefreshHolding = opts.onRefreshHolding || function() {};
+ self.onRefresh = opts.onRefresh || function() {};
+ self.onRefreshOpening = opts.onRefreshOpening || function() {};
+ self.onRefreshHolding = opts.onRefreshHolding || function() {};
window.ionic.onGesture('release', function(e) {
- _this._handleEndDrag(e);
- }, this.el);
+ self._handleEndDrag(e);
+ }, self.el);
window.ionic.onGesture('drag', function(e) {
- _this._handleDrag(e);
- }, this.el);
+ self._handleDrag(e);
+ }, self.el);
// Start the drag states
- this._initDrag();
+ self._initDrag();
},
/**
* Be sure to cleanup references.
*/
deregister: function() {
- this.el = null;
- this.listEl = null;
- this.scrollEl = null;
- this.scrollView = null;
+ this.el = this.listEl = this.scrollEl = this.scrollView = null;
+
+ // ensure no scrolls have been left frozen
+ if (this.isScrollFreeze) {
+ self.scrollView.freeze(false);
+ }
},
/**
@@ -428,28 +429,30 @@
* of active elements in order to figure out the viewport to render.
*/
didScroll: function(e) {
- if (this.isVirtual) {
- var itemHeight = this.itemHeight;
+ var self = this;
+
+ if (self.isVirtual) {
+ var itemHeight = self.itemHeight;
// TODO: This would be inaccurate if we are windowed
- var totalItems = this.listEl.children.length;
+ var totalItems = self.listEl.children.length;
// Grab the total height of the list
var scrollHeight = e.target.scrollHeight;
// Get the viewport height
- var viewportHeight = this.el.parentNode.offsetHeight;
+ var viewportHeight = self.el.parentNode.offsetHeight;
// scrollTop is the current scroll position
var scrollTop = e.scrollTop;
// High water is the pixel position of the first element to include (everything before
// that will be removed)
- var highWater = Math.max(0, e.scrollTop + this.virtualRemoveThreshold);
+ var highWater = Math.max(0, e.scrollTop + self.virtualRemoveThreshold);
// Low water is the pixel position of the last element to include (everything after
// that will be removed)
- var lowWater = Math.min(scrollHeight, Math.abs(e.scrollTop) + viewportHeight + this.virtualAddThreshold);
+ var lowWater = Math.min(scrollHeight, Math.abs(e.scrollTop) + viewportHeight + self.virtualAddThreshold);
// Compute how many items per viewport size can show
var itemsPerViewport = Math.floor((lowWater - highWater) / itemHeight);
@@ -460,12 +463,12 @@
var last = parseInt(Math.abs(lowWater / itemHeight), 10);
// Get the items we need to remove
- this._virtualItemsToRemove = Array.prototype.slice.call(this.listEl.children, 0, first);
+ self._virtualItemsToRemove = Array.prototype.slice.call(self.listEl.children, 0, first);
// Grab the nodes we will be showing
- var nodes = Array.prototype.slice.call(this.listEl.children, first, first + itemsPerViewport);
+ var nodes = Array.prototype.slice.call(self.listEl.children, first, first + itemsPerViewport);
- this.renderViewport && this.renderViewport(highWater, lowWater, first, last);
+ self.renderViewport && self.renderViewport(highWater, lowWater, first, last);
}
},
@@ -493,8 +496,6 @@
},
_initDrag: function() {
- //ionic.views.ListView.__super__._initDrag.call(this);
-
// Store the last one
if (this._lastDragOp) {
this._lastDragOp.deregister && this._lastDragOp.deregister();
@@ -517,74 +518,76 @@
_startDrag: function(e) {
- var _this = this;
+ var self = this;
var didStart = false;
- this._isDragging = false;
+ self._isDragging = false;
- var lastDragOp = this._lastDragOp;
+ var lastDragOp = self._lastDragOp;
var item;
// If we have an open SlideDrag and we're scrolling the list. Clear it.
- if (this._didDragUpOrDown && lastDragOp instanceof SlideDrag) {
+ if (self._didDragUpOrDown && lastDragOp instanceof SlideDrag) {
lastDragOp.clean && lastDragOp.clean();
}
// Check if this is a reorder drag
if (ionic.DomUtil.getParentOrSelfWithClass(e.target, ITEM_REORDER_BTN_CLASS) && (e.gesture.direction == 'up' || e.gesture.direction == 'down')) {
- item = this._getItem(e.target);
+ item = self._getItem(e.target);
if (item) {
- this._dragOp = new ReorderDrag({
- listEl: this.el,
+ self._dragOp = new ReorderDrag({
+ listEl: self.el,
el: item,
- scrollEl: this.scrollEl,
- scrollView: this.scrollView,
+ scrollEl: self.scrollEl,
+ scrollView: self.scrollView,
onReorder: function(el, start, end) {
- _this.onReorder && _this.onReorder(el, start, end);
+ self.onReorder && self.onReorder(el, start, end);
}
});
- this._dragOp.start(e);
+ self._dragOp.start(e);
e.preventDefault();
}
}
// Or check if this is a swipe to the side drag
- else if (!this._didDragUpOrDown && (e.gesture.direction == 'left' || e.gesture.direction == 'right') && Math.abs(e.gesture.deltaX) > 5) {
+ else if (!self._didDragUpOrDown && (e.gesture.direction == 'left' || e.gesture.direction == 'right') && Math.abs(e.gesture.deltaX) > 5) {
// Make sure this is an item with buttons
- item = this._getItem(e.target);
+ item = self._getItem(e.target);
if (item && item.querySelector('.item-options')) {
- this._dragOp = new SlideDrag({
- el: this.el,
+ self._dragOp = new SlideDrag({
+ el: self.el,
item: item,
- canSwipe: this.canSwipe
+ canSwipe: self.canSwipe
});
- this._dragOp.start(e);
+ self._dragOp.start(e);
e.preventDefault();
+ self.isScrollFreeze = self.scrollView.freeze(true);
}
}
// If we had a last drag operation and this is a new one on a different item, clean that last one
- if (lastDragOp && this._dragOp && !this._dragOp.isSameItem(lastDragOp) && e.defaultPrevented) {
+ if (lastDragOp && self._dragOp && !self._dragOp.isSameItem(lastDragOp) && e.defaultPrevented) {
lastDragOp.clean && lastDragOp.clean();
}
},
_handleEndDrag: function(e) {
- var _this = this;
+ var self = this;
+
+ self.isScrollFreeze = self.scrollView.freeze(false);
- this._didDragUpOrDown = false;
+ self._didDragUpOrDown = false;
- if (!this._dragOp) {
- //ionic.views.ListView.__super__._handleEndDrag.call(this, e);
+ if (!self._dragOp) {
return;
}
- this._dragOp.end(e, function() {
- _this._initDrag();
+ self._dragOp.end(e, function() {
+ self._initDrag();
});
},
@@ -592,26 +595,25 @@
* Process the drag event to move the item to the left or right.
*/
_handleDrag: function(e) {
- var _this = this, content, buttons;
+ var self = this, content, buttons;
if (Math.abs(e.gesture.deltaY) > 5) {
- this._didDragUpOrDown = true;
+ self._didDragUpOrDown = true;
}
// If we get a drag event, make sure we aren't in another drag, then check if we should
// start one
- if (!this.isDragging && !this._dragOp) {
- this._startDrag(e);
+ if (!self.isDragging && !self._dragOp) {
+ self._startDrag(e);
}
// No drag still, pass it up
- if (!this._dragOp) {
- //ionic.views.ListView.__super__._handleDrag.call(this, e);
+ if (!self._dragOp) {
return;
}
e.gesture.srcEvent.preventDefault();
- this._dragOp.drag(e);
+ self._dragOp.drag(e);
}
});
diff --git a/js/views/scrollView.js b/js/views/scrollView.js
index 9b1f879a29c..67debdd6d91 100644
--- a/js/views/scrollView.js
+++ b/js/views/scrollView.js
@@ -406,6 +406,13 @@ ionic.views.Scroll = ionic.views.View.inherit({
};
+ self.freeze = function(shouldFreeze) {
+ if (arguments.length) {
+ self.options.freeze = shouldFreeze;
+ }
+ return self.options.freeze;
+ };
+
self.setScrollStart = function() {
ionic.scroll.isScrolling = Math.abs(ionic.scroll.lastTop - self.__scrollTop) > 1;
clearTimeout(self.scrollTimer);
@@ -872,7 +879,7 @@ ionic.views.Scroll = ionic.views.View.inherit({
self.mouseWheel = ionic.animationFrameThrottle(function(e) {
var scrollParent = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'ionic-scroll');
- if (scrollParent === self.__container) {
+ if (!self.options.freeze && scrollParent === self.__container) {
self.hintResize();
self.scrollBy(