Expose an onScroll event

This commit is contained in:
Max Lynch
2013-12-05 19:30:18 -06:00
parent 6f7b9fdf80
commit 7bd2e5263d
7 changed files with 110 additions and 27 deletions

View File

@@ -650,6 +650,7 @@ angular.module('ionic.ui.content', [])
scope: {
onRefresh: '&',
onRefreshOpening: '&',
onScroll: '&',
refreshComplete: '=',
scroll: '@',
hasScrollX: '@',
@@ -731,6 +732,14 @@ angular.module('ionic.ui.content', [])
});
}
$element.bind('scroll', function(e) {
$scope.onScroll({
event: e,
scrollTop: e.detail.scrollTop,
scrollLeft: e.detail.scrollLeft
});
});
$scope.$parent.$on('scroll.refreshComplete', function(e) {
sv && sv.finishPullToRefresh();
});

40
dist/js/ionic.js vendored
View File

@@ -293,7 +293,7 @@ window.ionic = {
// Map some convenient top-level functions for event handling
ionic.on = function() { ionic.EventController.on.apply(ionic.EventController, arguments); };
ionic.off = function() { ionic.EventController.off.apply(ionic.EventController, arguments); };
ionic.trigger = function() { ionic.EventController.trigger.apply(ionic.EventController.trigger, arguments); };
ionic.trigger = ionic.EventController.trigger;//function() { ionic.EventController.trigger.apply(ionic.EventController.trigger, arguments); };
ionic.onGesture = function() { return ionic.EventController.onGesture.apply(ionic.EventController.onGesture, arguments); };
ionic.offGesture = function() { return ionic.EventController.offGesture.apply(ionic.EventController.offGesture, arguments); };
@@ -2316,8 +2316,9 @@ var Scroller;
/**
* A pure logic 'component' for 'virtual' scrolling/zooming.
*/
ionic.views.Scroll = ionic.views.View.inherit({
initialize: function(options) {
ionic.views.Scroll = ionic.views.View.inherit({
initialize: function(options) {
var self = this;
this.__container = options.el;
this.__content = options.el.firstElementChild;
@@ -2367,17 +2368,35 @@ var Scroller;
scrollingComplete: NOOP,
/** This configures the amount of change applied to deceleration when reaching boundaries **/
penetrationDeceleration : 0.03,
penetrationDeceleration : 0.03,
/** This configures the amount of change applied to acceleration when reaching boundaries **/
penetrationAcceleration : 0.08
/** This configures the amount of change applied to acceleration when reaching boundaries **/
penetrationAcceleration : 0.08,
// The ms interval for triggering scroll events
scrollEventInterval: 50
};
for (var key in options) {
this.options[key] = options[key];
}
this.triggerScrollEvent = ionic.throttle(function() {
ionic.trigger('scroll', {
scrollTop: self.__scrollTop,
scrollLeft: self.__scrollLeft,
target: self.__container
});
}, this.options.scrollEventInterval);
this.triggerScrollEndEvent = function() {
ionic.trigger('scrollend', {
scrollTop: self.__scrollTop,
scrollLeft: self.__scrollLeft,
target: self.__container
});
};
// Get the render update function, initialize event handlers,
// and calculate the size of the scroll container
this.__callback = this.getRenderFn();
@@ -2634,6 +2653,8 @@ var Scroller;
*/
getRenderFn: function() {
var self = this;
var content = this.__content;
var docStyle = document.documentElement.style;
@@ -2663,13 +2684,15 @@ var Scroller;
if (helperElem.style[perspectiveProperty] !== undef) {
return function(left, top, zoom) {
content.style[transformProperty] = 'translate3d(' + (-left) + 'px,' + (-top) + 'px,0) scale(' + zoom + ')';
content.style[transformProperty] = 'translate3d(' + (-left) + 'px,' + (-top) + 'px,0)';
self.triggerScrollEvent();
};
} else if (helperElem.style[transformProperty] !== undef) {
return function(left, top, zoom) {
content.style[transformProperty] = 'translate(' + (-left) + 'px,' + (-top) + 'px) scale(' + zoom + ')';
content.style[transformProperty] = 'translate(' + (-left) + 'px,' + (-top) + 'px)';
self.triggerScrollEvent();
};
} else {
@@ -2678,6 +2701,7 @@ var Scroller;
content.style.marginLeft = left ? (-left/zoom) + 'px' : '';
content.style.marginTop = top ? (-top/zoom) + 'px' : '';
content.style.zoom = zoom || '';
self.triggerScrollEvent();
};
}

View File

@@ -27,6 +27,7 @@ angular.module('ionic.ui.content', [])
scope: {
onRefresh: '&',
onRefreshOpening: '&',
onScroll: '&',
refreshComplete: '=',
scroll: '@',
hasScrollX: '@',
@@ -108,6 +109,14 @@ angular.module('ionic.ui.content', [])
});
}
$element.bind('scroll', function(e) {
$scope.onScroll({
event: e,
scrollTop: e.detail.scrollTop,
scrollLeft: e.detail.scrollLeft
});
});
$scope.$parent.$on('scroll.refreshComplete', function(e) {
sv && sv.finishPullToRefresh();
});

View File

@@ -54,24 +54,17 @@
</style>
</head>
<body>
<body ng-controller="ThisCtrl">
<pane>
<header-bar
title="'Title'"
type="bar-primary"></header-bar>
<header-bar id="header" title="'Title'" type="bar-primary" hides-header></header-bar>
<div class="bar bar-positive bar-subheader">
<a href="#" class="button button-danger button-clear">Edit</a>
<h1 class="title">Scroll Me</h1>
<a href="#" class="button button-danger button-clear">Delete</a>
</div>
<content
<content id="container"
on-scroll="onScroll(event, scrollTop, scrollLeft)"
on-refresh="onRefresh()"
on-refresh-opening="onRefreshOpening(amount)"
refresh-complete="refreshComplete"
has-tabs="true"
has-header="true"
has-subheader="true"
>
<refresher></refresher>
<ul class="list" ng-controller="AppCtrl">
@@ -106,6 +99,30 @@
<script>
angular.module('navTest', ['ionic'])
.directive('hidesHeader', function() {
return {
link: function($scope, $element, $attr) {
var startTop = $element[0].offsetTop;
console.log("Starting", startTop);
}
}
})
.controller('ThisCtrl', function($scope) {
var header = document.getElementById('header');
var content = document.getElementById('container');
var startTop = header.offsetTop;
$scope.onScroll = function(event, scrollTop, scrollLeft) {
if(scrollTop > startTop) {
var diff = scrollTop - startTop;
console.log(diff);
header.style.webkitTransform = 'translate3d(0px, -' + diff + 'px, 0)';
content.style.marginTop = -diff + 'px';
}
console.log('Scroll', scrollTop, scrollLeft);
};
})
.controller('AppCtrl', function($scope, $compile, $timeout, $element) {
$scope.items = [];
for(var i = 0; i < 70; i++) {

View File

View File

@@ -88,7 +88,7 @@
// Map some convenient top-level functions for event handling
ionic.on = function() { ionic.EventController.on.apply(ionic.EventController, arguments); };
ionic.off = function() { ionic.EventController.off.apply(ionic.EventController, arguments); };
ionic.trigger = function() { ionic.EventController.trigger.apply(ionic.EventController.trigger, arguments); };
ionic.trigger = ionic.EventController.trigger;//function() { ionic.EventController.trigger.apply(ionic.EventController.trigger, arguments); };
ionic.onGesture = function() { return ionic.EventController.onGesture.apply(ionic.EventController.onGesture, arguments); };
ionic.offGesture = function() { return ionic.EventController.offGesture.apply(ionic.EventController.offGesture, arguments); };

View File

@@ -281,8 +281,9 @@ var Scroller;
/**
* A pure logic 'component' for 'virtual' scrolling/zooming.
*/
ionic.views.Scroll = ionic.views.View.inherit({
initialize: function(options) {
ionic.views.Scroll = ionic.views.View.inherit({
initialize: function(options) {
var self = this;
this.__container = options.el;
this.__content = options.el.firstElementChild;
@@ -332,17 +333,35 @@ var Scroller;
scrollingComplete: NOOP,
/** This configures the amount of change applied to deceleration when reaching boundaries **/
penetrationDeceleration : 0.03,
penetrationDeceleration : 0.03,
/** This configures the amount of change applied to acceleration when reaching boundaries **/
penetrationAcceleration : 0.08
/** This configures the amount of change applied to acceleration when reaching boundaries **/
penetrationAcceleration : 0.08,
// The ms interval for triggering scroll events
scrollEventInterval: 50
};
for (var key in options) {
this.options[key] = options[key];
}
this.triggerScrollEvent = ionic.throttle(function() {
ionic.trigger('scroll', {
scrollTop: self.__scrollTop,
scrollLeft: self.__scrollLeft,
target: self.__container
});
}, this.options.scrollEventInterval);
this.triggerScrollEndEvent = function() {
ionic.trigger('scrollend', {
scrollTop: self.__scrollTop,
scrollLeft: self.__scrollLeft,
target: self.__container
});
};
// Get the render update function, initialize event handlers,
// and calculate the size of the scroll container
this.__callback = this.getRenderFn();
@@ -599,6 +618,8 @@ var Scroller;
*/
getRenderFn: function() {
var self = this;
var content = this.__content;
var docStyle = document.documentElement.style;
@@ -628,13 +649,15 @@ var Scroller;
if (helperElem.style[perspectiveProperty] !== undef) {
return function(left, top, zoom) {
content.style[transformProperty] = 'translate3d(' + (-left) + 'px,' + (-top) + 'px,0) scale(' + zoom + ')';
content.style[transformProperty] = 'translate3d(' + (-left) + 'px,' + (-top) + 'px,0)';
self.triggerScrollEvent();
};
} else if (helperElem.style[transformProperty] !== undef) {
return function(left, top, zoom) {
content.style[transformProperty] = 'translate(' + (-left) + 'px,' + (-top) + 'px) scale(' + zoom + ')';
content.style[transformProperty] = 'translate(' + (-left) + 'px,' + (-top) + 'px)';
self.triggerScrollEvent();
};
} else {
@@ -643,6 +666,7 @@ var Scroller;
content.style.marginLeft = left ? (-left/zoom) + 'px' : '';
content.style.marginTop = top ? (-top/zoom) + 'px' : '';
content.style.zoom = zoom || '';
self.triggerScrollEvent();
};
}