Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 94fb282

Browse files
oliversalzburgFoxandxss
authored andcommitted
fix(typeahead): dangling event listeners
Fixes #4632 Closes #4636
1 parent 97fd37e commit 94fb282

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

src/typeahead/test/typeahead.spec.js

+40-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
describe('typeahead tests', function() {
2-
var $scope, $compile, $document, $templateCache, $timeout;
2+
var $scope, $compile, $document, $templateCache, $timeout, $window;
33
var changeInputValueTo;
44

55
beforeEach(module('ui.bootstrap.typeahead'));
@@ -25,7 +25,7 @@ describe('typeahead tests', function() {
2525
};
2626
});
2727
}));
28-
beforeEach(inject(function(_$rootScope_, _$compile_, _$document_, _$templateCache_, _$timeout_, $sniffer) {
28+
beforeEach(inject(function(_$rootScope_, _$compile_, _$document_, _$templateCache_, _$timeout_, _$window_, $sniffer) {
2929
$scope = _$rootScope_;
3030
$scope.source = ['foo', 'bar', 'baz'];
3131
$scope.states = [
@@ -36,6 +36,7 @@ describe('typeahead tests', function() {
3636
$document = _$document_;
3737
$templateCache = _$templateCache_;
3838
$timeout = _$timeout_;
39+
$window = _$window_;
3940
changeInputValueTo = function(element, value) {
4041
var inputEl = findInput(element);
4142
inputEl.val(value);
@@ -870,6 +871,11 @@ describe('typeahead tests', function() {
870871
});
871872

872873
describe('append to body', function() {
874+
afterEach(function() {
875+
angular.element($window).off('resize');
876+
$document.find('body').off('scroll');
877+
});
878+
873879
it('append typeahead results to body', function() {
874880
var element = prepareInputEl('<div><input ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-append-to-body="true"></div>');
875881
changeInputValueTo(element, 'ba');
@@ -1012,6 +1018,34 @@ describe('typeahead tests', function() {
10121018
expect(element).toBeOpenWithActive(3, 0);
10131019
});
10141020
});
1021+
1022+
describe('event listeners', function() {
1023+
afterEach(function() {
1024+
angular.element($window).off('resize');
1025+
$document.find('body').off('scroll');
1026+
});
1027+
1028+
it('should register event listeners when attached to body', function() {
1029+
spyOn(window, 'addEventListener');
1030+
spyOn(document.body, 'addEventListener');
1031+
1032+
var element = prepareInputEl('<div><input ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-append-to-body="true"></div>');
1033+
1034+
expect(window.addEventListener).toHaveBeenCalledWith('resize', jasmine.any(Function), false);
1035+
expect(document.body.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), false);
1036+
});
1037+
1038+
it('should remove event listeners when attached to body', function() {
1039+
spyOn(window, 'removeEventListener');
1040+
spyOn(document.body, 'removeEventListener');
1041+
1042+
var element = prepareInputEl('<div><input ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-append-to-body="true"></div>');
1043+
$scope.$destroy();
1044+
1045+
expect(window.removeEventListener).toHaveBeenCalledWith('resize', jasmine.any(Function), false);
1046+
expect(document.body.removeEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), false);
1047+
});
1048+
});
10151049
});
10161050

10171051
/* Deprecation tests below */
@@ -1049,15 +1083,15 @@ describe('typeahead deprecation', function() {
10491083
expect($log.warn.calls.argsFor(1)).toEqual(['typeahead is now deprecated. Use uib-typeahead instead.']);
10501084
expect($log.warn.calls.argsFor(2)).toEqual(['typeahead-popup is now deprecated. Use uib-typeahead-popup instead.']);
10511085
}));
1052-
1086+
10531087
it('should deprecate typeaheadMatch', inject(function($compile, $log, $rootScope, $templateCache, $sniffer){
10541088
spyOn($log, 'warn');
1055-
1089+
10561090
var element = '<div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>';
10571091
element = $compile(element)($rootScope);
10581092
$rootScope.$digest();
1059-
1093+
10601094
expect($log.warn.calls.count()).toBe(1);
10611095
expect($log.warn.calls.argsFor(0)).toEqual(['typeahead-match is now deprecated. Use uib-typeahead-match instead.']);
10621096
}));
1063-
});
1097+
});

src/typeahead/typeahead.js

+10
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
359359
if (appendToBody || appendToElementId) {
360360
$popup.remove();
361361
}
362+
363+
if (appendToBody) {
364+
angular.element($window).unbind('resize', fireRecalculating);
365+
$document.find('body').unbind('scroll', fireRecalculating);
366+
}
362367
// Prevent jQuery cache memory leak
363368
popUpEl.remove();
364369
});
@@ -937,6 +942,11 @@ angular.module('ui.bootstrap.typeahead')
937942
if (appendToBody || appendToElementId) {
938943
$popup.remove();
939944
}
945+
946+
if (appendToBody) {
947+
angular.element($window).unbind('resize', fireRecalculating);
948+
$document.find('body').unbind('scroll', fireRecalculating);
949+
}
940950
// Prevent jQuery cache memory leak
941951
popUpEl.remove();
942952
});

0 commit comments

Comments
 (0)