mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
/**
* @ngdoc method
* @name $ionicScrollDelegate#rememberScrollPosition
* @description
*
* When this scroll area is destroyed, its last scroll position will be
* saved using the given id.
*
* @param {string} id The identifier for this saved scroll position.
*/
/**
* @ngdoc method
* @name $ionicScrollDelegate#scrollToRememberedPosition
* @description
*
* If a scroll position was remembered using the given id, loads the
* remembered scroll position and scrolls there.
*
* @param {string} id The identifier for this saved scroll position.
* @param {boolean=} shouldAnimate Whether to animate the scroll.
*/
267 lines
8.7 KiB
JavaScript
267 lines
8.7 KiB
JavaScript
describe('Ionic ScrollDelegate Service', function() {
|
|
var $ionicScrollDelegate, rootScope, compile, timeout, document;
|
|
|
|
beforeEach(module('ionic'));
|
|
|
|
beforeEach(inject(function(_$ionicScrollDelegate_, $rootScope, $timeout, $compile, $document) {
|
|
$ionicScrollDelegate = _$ionicScrollDelegate_;
|
|
document = $document;
|
|
rootScope = $rootScope;
|
|
timeout = $timeout;
|
|
compile = $compile;
|
|
}));
|
|
|
|
it('should just return rootScope if no scrollCtrl', inject(function($rootScope) {
|
|
expect(function() {
|
|
$ionicScrollDelegate($rootScope);
|
|
}).not.toThrow();
|
|
expect($ionicScrollDelegate($rootScope).getScrollView()).toBeFalsy();
|
|
}));
|
|
|
|
it('Should get scroll view', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>')(scope);
|
|
var sv = $ionicScrollDelegate(scope).getScrollView();
|
|
expect(sv).not.toBe(undefined);
|
|
});
|
|
|
|
it('should resize', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>')(scope);
|
|
var del = $ionicScrollDelegate(scope);
|
|
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'resize');
|
|
spyOn(sv, 'scrollTo');
|
|
|
|
del.resize();
|
|
timeout.flush();
|
|
expect(sv.resize).toHaveBeenCalled();
|
|
});
|
|
|
|
it('scroll event', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>')(scope);
|
|
scope = el.scope();
|
|
scope.$apply();
|
|
var top, left;
|
|
scope.$onScroll = jasmine.createSpy('scroll').andCallFake(function(data) {
|
|
top = data.scrollTop;
|
|
left = data.scrollLeft;
|
|
});
|
|
ionic.trigger('scroll', {target: el[0]});
|
|
expect(scope.$onScroll).toHaveBeenCalled();
|
|
expect(top).toBe(0);
|
|
expect(left).toBe(0);
|
|
|
|
ionic.trigger('scroll', {target: el[0], scrollTop: 3, scrollLeft: 4});
|
|
expect(top).toBe(3);
|
|
expect(left).toBe(4);
|
|
});
|
|
|
|
testWithAnimate(true);
|
|
testWithAnimate(false);
|
|
function testWithAnimate(animate) {
|
|
describe('with animate='+animate, function() {
|
|
|
|
it('should tapScrollToTop', function() {
|
|
var scope = rootScope.$new();
|
|
var el = angular.element('<div>' +
|
|
'<div class="not-button"></div>' +
|
|
'<div class="button"></div>' +
|
|
'</div>');
|
|
//ionic.trigger() REALLY doesnt want to work with tap,
|
|
//so we just mock on to catch the callback and use that...
|
|
var callback;
|
|
var del = $ionicScrollDelegate(scope);
|
|
spyOn(ionic, 'on').andCallFake(function(eventName, cb) {
|
|
callback = cb;
|
|
});
|
|
del.tapScrollToTop(el, animate);
|
|
|
|
spyOn(del, 'scrollTop');
|
|
//Don't test the rectContains part, too much to mock
|
|
spyOn(ionic.DomUtil, 'rectContains').andCallFake(function() {
|
|
return true;
|
|
});
|
|
callback({
|
|
target: el[0].querySelector('.not-button'),
|
|
gesture:{ touches:[{}] }
|
|
});
|
|
expect(del.scrollTop).toHaveBeenCalledWith(animate);
|
|
|
|
del.scrollTop.reset();
|
|
callback({
|
|
target: el[0].querySelector('.button')
|
|
});
|
|
expect(del.scrollTop).not.toHaveBeenCalled();
|
|
});
|
|
it('should resize & scroll top', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content start-y="100"></ion-content>')(scope);
|
|
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'resize');
|
|
spyOn(sv, 'scrollTo');
|
|
del.scrollTop(animate);
|
|
|
|
timeout.flush();
|
|
expect(sv.resize).toHaveBeenCalled();
|
|
expect(sv.scrollTo.mostRecentCall.args).toEqual([0, 0, animate]);
|
|
});
|
|
|
|
it('should resize & scroll bottom', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content start-y="100"><br/><br/></ion-content>')(scope);
|
|
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'getScrollMax').andCallFake(function() {
|
|
return { left: 10, top: 11 };
|
|
});
|
|
spyOn(sv, 'resize');
|
|
spyOn(sv, 'scrollTo');
|
|
var max = sv.getScrollMax();
|
|
del.scrollBottom(animate);
|
|
|
|
timeout.flush();
|
|
expect(sv.resize).toHaveBeenCalled();
|
|
expect(sv.scrollTo.mostRecentCall.args).toEqual([max.left, max.top, animate]);
|
|
});
|
|
|
|
it('should resize & scrollTo', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content start-y="100"><br/><br/></ion-content>')(scope);
|
|
var del = $ionicScrollDelegate(scope);
|
|
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'scrollTo');
|
|
spyOn(sv, 'resize');
|
|
del.scrollTo(2, 3, animate);
|
|
|
|
timeout.flush();
|
|
expect(sv.resize).toHaveBeenCalled();
|
|
expect(sv.scrollTo.mostRecentCall.args).toEqual([2, 3, animate]);
|
|
});
|
|
|
|
it('should throw error on rememberScroll if no id', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>');
|
|
var del = $ionicScrollDelegate(scope);
|
|
expect(del.rememberScrollPosition).toThrow();
|
|
});
|
|
|
|
it('scrollToRememberedPosition should scroll if exists', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>')(scope);
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
scope.$apply();
|
|
$ionicScrollDelegate._rememberedScrollValues['1'] = {
|
|
left: 3,
|
|
top: 4
|
|
};
|
|
del.scrollToRememberedPosition('1', animate);
|
|
spyOn(sv, 'scrollTo');
|
|
timeout.flush();
|
|
expect(sv.scrollTo).toHaveBeenCalledWith(3, 4, animate);
|
|
});
|
|
|
|
it('should save on destroy for rememberScrollPosition', function() {
|
|
var scope = rootScope.$new();
|
|
var el = compile('<ion-content></ion-content>')(scope);
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
scope.$apply();
|
|
$ionicScrollDelegate._rememberedScrollValues['1'] = {
|
|
left: -1,
|
|
top: -1
|
|
};
|
|
del.rememberScrollPosition('1', animate);
|
|
spyOn(sv, 'getValues').andCallFake(function() {
|
|
return { foo: 'bar' };
|
|
});
|
|
scope.$destroy();
|
|
expect(sv.getValues).toHaveBeenCalled();
|
|
expect($ionicScrollDelegate._rememberedScrollValues['1']).toEqual({
|
|
foo: 'bar'
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('anchorScroll', function() {
|
|
function setLocationHash(hash) {
|
|
inject(function($location) {
|
|
$location.hash = function() { return hash; };
|
|
});
|
|
}
|
|
|
|
beforeEach(module('ionic'));
|
|
|
|
testWithAnimate(true);
|
|
testWithAnimate(false);
|
|
|
|
function testWithAnimate(animate) {
|
|
describe('with animate=' + animate, function() {
|
|
var contentEl, scope, $ionicScrollDelegate, timeout;
|
|
beforeEach(inject(function($rootScope, $compile, $timeout, $document, _$ionicScrollDelegate_) {
|
|
scope = $rootScope.$new();
|
|
contentEl = $compile('<ion-content></ion-content>')(scope);
|
|
|
|
document.body.appendChild(contentEl[0]);
|
|
$ionicScrollDelegate = _$ionicScrollDelegate_;
|
|
timeout = $timeout;
|
|
$rootScope.$apply();
|
|
}));
|
|
|
|
it('should anchorScroll to an element with id', function() {
|
|
var anchorMe = angular.element('<div id="anchorMe">');
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'scrollTo');
|
|
spyOn(ionic.DomUtil, 'getPositionInParent').andCallFake(function() {
|
|
return { left: 2, top: 1 };
|
|
});
|
|
|
|
setLocationHash('anchorMe');
|
|
contentEl.append(anchorMe);
|
|
|
|
del.anchorScroll(animate);
|
|
timeout.flush();
|
|
expect(sv.scrollTo).toHaveBeenCalledWith(2, 1, animate);
|
|
});
|
|
|
|
it('should anchorScroll to top if !$location.hash()', function() {
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'scrollTo');
|
|
spyOn(ionic.DomUtil, 'getPositionInParent');
|
|
del.anchorScroll(animate);
|
|
timeout.flush();
|
|
|
|
expect(sv.scrollTo).toHaveBeenCalledWith(0, 0, animate);
|
|
expect(ionic.DomUtil.getPositionInParent).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should anchorScroll to top if element with hash id doesnt exist', function() {
|
|
var del = $ionicScrollDelegate(scope);
|
|
var sv = del.getScrollView();
|
|
spyOn(sv, 'scrollTo');
|
|
spyOn(ionic.DomUtil, 'getPositionInParent');
|
|
|
|
setLocationHash('doesnotexist');
|
|
del.anchorScroll(animate);
|
|
timeout.flush();
|
|
|
|
expect(sv.scrollTo).toHaveBeenCalledWith(0, 0, animate);
|
|
expect(ionic.DomUtil.getPositionInParent).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
}
|
|
|
|
});
|
|
|