ionic-angular
Version:
[](https://circleci.com/gh/driftyco/ionic)
186 lines (170 loc) • 7.58 kB
JavaScript
/**
* @ngdoc directive
* @name ionContent
* @module ionic
* @delegate ionic.service:$ionicScrollDelegate
* @restrict E
*
* @description
* The ionContent directive provides an easy to use content area that can be configured
* to use Ionic's custom Scroll View, or the built in overflow scrolling of the browser.
*
* While we recommend using the custom Scroll features in Ionic in most cases, sometimes
* (for performance reasons) only the browser's native overflow scrolling will suffice,
* and so we've made it easy to toggle between the Ionic scroll implementation and
* overflow scrolling.
*
* You can implement pull-to-refresh with the {@link ionic.directive:ionRefresher}
* directive, and infinite scrolling with the {@link ionic.directive:ionInfiniteScroll}
* directive.
*
* If there is any dynamic content inside the ion-content, be sure to call `.resize()` with {@link ionic.service:$ionicScrollDelegate}
* after the content has been added.
*
* Be aware that this directive gets its own child scope. If you do not understand why this
* is important, you can read [https://docs.angularjs.org/guide/scope](https://docs.angularjs.org/guide/scope).
*
* @param {string=} delegate-handle The handle used to identify this scrollView
* with {@link ionic.service:$ionicScrollDelegate}.
* @param {string=} direction Which way to scroll. 'x' or 'y' or 'xy'. Default 'y'.
* @param {boolean=} locking Whether to lock scrolling in one direction at a time. Useful to set to false when zoomed in or scrolling in two directions. Default true.
* @param {boolean=} padding Whether to add padding to the content.
* Defaults to true on iOS, false on Android.
* @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true.
* @param {boolean=} overflow-scroll Whether to use overflow-scrolling instead of
* Ionic scroll. See {@link ionic.provider:$ionicConfigProvider} to set this as the global default.
* @param {boolean=} scrollbar-x Whether to show the horizontal scrollbar. Default true.
* @param {boolean=} scrollbar-y Whether to show the vertical scrollbar. Default true.
* @param {string=} start-x Initial horizontal scroll position. Default 0.
* @param {string=} start-y Initial vertical scroll position. Default 0.
* @param {expression=} on-scroll Expression to evaluate when the content is scrolled.
* @param {expression=} on-scroll-complete Expression to evaluate when a scroll action completes. Has access to 'scrollLeft' and 'scrollTop' locals.
* @param {boolean=} has-bouncing Whether to allow scrolling to bounce past the edges
* of the content. Defaults to true on iOS, false on Android.
* @param {number=} scroll-event-interval Number of milliseconds between each firing of the 'on-scroll' expression. Default 10.
*/
IonicModule
.directive('ionContent', [
'$timeout',
'$controller',
'$ionicBind',
'$ionicConfig',
function($timeout, $controller, $ionicBind, $ionicConfig) {
return {
restrict: 'E',
require: '^?ionNavView',
scope: true,
priority: 800,
compile: function(element, attr) {
var innerElement;
var scrollCtrl;
element.addClass('scroll-content ionic-scroll');
if (attr.scroll != 'false') {
//We cannot use normal transclude here because it breaks element.data()
//inheritance on compile
innerElement = jqLite('<div class="scroll"></div>');
innerElement.append(element.contents());
element.append(innerElement);
} else {
element.addClass('scroll-content-false');
}
var nativeScrolling = attr.overflowScroll !== "false" && (attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling());
// collection-repeat requires JS scrolling
if (nativeScrolling) {
nativeScrolling = !element[0].querySelector('[collection-repeat]');
}
return { pre: prelink };
function prelink($scope, $element, $attr) {
var parentScope = $scope.$parent;
$scope.$watch(function() {
return (parentScope.$hasHeader ? ' has-header' : '') +
(parentScope.$hasSubheader ? ' has-subheader' : '') +
(parentScope.$hasFooter ? ' has-footer' : '') +
(parentScope.$hasSubfooter ? ' has-subfooter' : '') +
(parentScope.$hasTabs ? ' has-tabs' : '') +
(parentScope.$hasTabsTop ? ' has-tabs-top' : '');
}, function(className, oldClassName) {
$element.removeClass(oldClassName);
$element.addClass(className);
});
//Only this ionContent should use these variables from parent scopes
$scope.$hasHeader = $scope.$hasSubheader =
$scope.$hasFooter = $scope.$hasSubfooter =
$scope.$hasTabs = $scope.$hasTabsTop =
false;
$ionicBind($scope, $attr, {
$onScroll: '&onScroll',
$onScrollComplete: '&onScrollComplete',
hasBouncing: '@',
padding: '@',
direction: '@',
scrollbarX: '@',
scrollbarY: '@',
startX: '@',
startY: '@',
scrollEventInterval: '@'
});
$scope.direction = $scope.direction || 'y';
if (isDefined($attr.padding)) {
$scope.$watch($attr.padding, function(newVal) {
(innerElement || $element).toggleClass('padding', !!newVal);
});
}
if ($attr.scroll === "false") {
//do nothing
} else {
var scrollViewOptions = {};
// determined in compile phase above
if (nativeScrolling) {
// use native scrolling
$element.addClass('overflow-scroll');
scrollViewOptions = {
el: $element[0],
delegateHandle: attr.delegateHandle,
startX: $scope.$eval($scope.startX) || 0,
startY: $scope.$eval($scope.startY) || 0,
nativeScrolling: true
};
} else {
// Use JS scrolling
scrollViewOptions = {
el: $element[0],
delegateHandle: attr.delegateHandle,
locking: (attr.locking || 'true') === 'true',
bouncing: $scope.$eval($scope.hasBouncing),
startX: $scope.$eval($scope.startX) || 0,
startY: $scope.$eval($scope.startY) || 0,
scrollbarX: $scope.$eval($scope.scrollbarX) !== false,
scrollbarY: $scope.$eval($scope.scrollbarY) !== false,
scrollingX: $scope.direction.indexOf('x') >= 0,
scrollingY: $scope.direction.indexOf('y') >= 0,
scrollEventInterval: parseInt($scope.scrollEventInterval, 10) || 10,
scrollingComplete: onScrollComplete
};
}
// init scroll controller with appropriate options
scrollCtrl = $controller('$ionicScroll', {
$scope: $scope,
scrollViewOptions: scrollViewOptions
});
$scope.scrollCtrl = scrollCtrl;
$scope.$on('$destroy', function() {
if (scrollViewOptions) {
scrollViewOptions.scrollingComplete = noop;
delete scrollViewOptions.el;
}
innerElement = null;
$element = null;
attr.$$element = null;
});
}
function onScrollComplete() {
$scope.$onScrollComplete({
scrollTop: scrollCtrl.scrollView.__scrollTop,
scrollLeft: scrollCtrl.scrollView.__scrollLeft
});
}
}
}
};
}]);