Skip to content

Commit 03d0fd7

Browse files
mariocasciarofernando-sendMail
authored andcommitted
feat(dropdown): Make Auto-Close Dropdowns optional.
Fixes angular-ui#2218 Closes angular-ui#3045
1 parent 967a7d3 commit 03d0fd7

File tree

3 files changed

+7
-70
lines changed

3 files changed

+7
-70
lines changed

src/dropdown/docs/readme.md

-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@
22
Dropdown is a simple directive which will toggle a dropdown menu on click or programmatically.
33
You can either use `is-open` to toggle or add inside a `<a dropdown-toggle>` element to toggle it when is clicked.
44
There is also the `on-toggle(open)` optional expression fired when dropdown changes state.
5-
6-
Add `dropdown-append-to-body` to the `dropdown` element to append to the inner `dropdown-menu` to the body.
7-
This is useful when the dropdown button is inside a div with `overflow: hidden`, and the menu would otherwise be hidden.
8-
95
By default the dropdown will automatically close if any of its elements is clicked, you can change this behavior by setting the `auto-close` option as follows:
106

117
* `always` - (Default) automatically closes the dropdown when any of its elements is clicked.
128
* `outsideClick` - closes the dropdown automatically only when the user clicks any element outside the dropdown.
139
* `disabled` - disables the auto close. You can then control the open/close status of the dropdown manually, by using `is-open`. Please notice that the dropdown will still close if the toggle is clicked, the `esc` key is pressed or another dropdown is open.
14-

src/dropdown/dropdown.js

+3-38
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
1+
angular.module('ui.bootstrap.dropdown', [])
22

33
.constant('dropdownConfig', {
44
openClass: 'open'
@@ -40,14 +40,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
4040
return;
4141
}
4242

43-
<<<<<<< HEAD
4443
var $element = openScope.getElement();
4544
if( evt && openScope.getAutoClose() === 'outsideClick' && $element && $element[0].contains(evt.target) ) {
4645
return;
4746
}
4847

49-
=======
50-
>>>>>>> fix(dropdown): Fix $digest:inprog on dropdown dismissal
5148
openScope.isOpen = false;
5249

5350
if (!$rootScope.$$phase) {
@@ -63,14 +60,13 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
6360
};
6461
}])
6562

66-
.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) {
63+
.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {
6764
var self = this,
6865
scope = $scope.$new(), // create a child scope so we are not polluting original one
6966
openClass = dropdownConfig.openClass,
7067
getIsOpen,
7168
setIsOpen = angular.noop,
72-
toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
73-
appendToBody = false;
69+
toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop;
7470

7571
this.init = function( element ) {
7672
self.$element = element;
@@ -83,15 +79,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
8379
scope.isOpen = !!value;
8480
});
8581
}
86-
87-
appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
88-
89-
if ( appendToBody && self.dropdownMenu ) {
90-
$document.find('body').append( self.dropdownMenu );
91-
element.on('$destroy', function handleDestroyEvent() {
92-
self.dropdownMenu.remove();
93-
});
94-
}
9582
};
9683

9784
this.toggle = function( open ) {
@@ -122,15 +109,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
122109
};
123110

124111
scope.$watch('isOpen', function( isOpen, wasOpen ) {
125-
if ( appendToBody && self.dropdownMenu ) {
126-
var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true);
127-
self.dropdownMenu.css({
128-
top: pos.top + 'px',
129-
left: pos.left + 'px',
130-
display: isOpen ? 'block' : 'none'
131-
});
132-
}
133-
134112
$animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);
135113

136114
if ( isOpen ) {
@@ -164,19 +142,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
164142
};
165143
})
166144

167-
.directive('dropdownMenu', function() {
168-
return {
169-
restrict: 'AC',
170-
require: '?^dropdown',
171-
link: function(scope, element, attrs, dropdownCtrl) {
172-
if ( !dropdownCtrl ) {
173-
return;
174-
}
175-
dropdownCtrl.dropdownMenu = element;
176-
}
177-
};
178-
})
179-
180145
.directive('dropdownToggle', function() {
181146
return {
182147
require: '?^dropdown',

src/dropdown/test/dropdown.spec.js

+4-27
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ describe('dropdownToggle', function() {
99
$document = _$document_;
1010
}));
1111

12-
afterEach(function() {
13-
element.remove();
14-
});
15-
1612
var clickDropdownToggle = function(elm) {
1713
elm = elm || element;
1814
elm.find('a[dropdown-toggle]').click();
@@ -54,6 +50,7 @@ describe('dropdownToggle', function() {
5450
var optionEl = element.find('ul > li').eq(0).find('a').eq(0);
5551
optionEl.click();
5652
expect(element.hasClass('open')).toBe(false);
53+
element.remove();
5754
});
5855

5956
it('should close on document click', function() {
@@ -69,6 +66,7 @@ describe('dropdownToggle', function() {
6966
triggerKeyDown($document, 27);
7067
expect(element.hasClass('open')).toBe(false);
7168
expect(isFocused(element.find('a'))).toBe(true);
69+
element.remove();
7270
});
7371

7472
it('should not close on backspace key', function() {
@@ -180,29 +178,6 @@ describe('dropdownToggle', function() {
180178

181179
expect(element.hasClass('open')).toBe(false);
182180
});
183-
<<<<<<< HEAD
184-
});
185-
186-
describe('using dropdown-append-to-body', function() {
187-
function dropdown() {
188-
return $compile('<li dropdown dropdown-append-to-body><a href dropdown-toggle></a><ul class="dropdown-menu" id="dropdown-menu"><li><a href>Hello On Body</a></li></ul></li>')($rootScope);
189-
}
190-
191-
beforeEach(function() {
192-
element = dropdown();
193-
});
194-
195-
it('adds the menu to the body', function() {
196-
expect($document.find('#dropdown-menu').parent()[0]).toBe($document.find('body')[0]);
197-
});
198-
199-
it('removes the menu when the dropdown is removed', function() {
200-
element.remove();
201-
$rootScope.$digest();
202-
expect($document.find('#dropdown-menu').length).toEqual(0);
203-
});
204-
=======
205-
>>>>>>> fix(dropdown): Fix $digest:inprog on dropdown dismissal
206181
});
207182

208183
describe('integration with $location URL rewriting', function() {
@@ -281,6 +256,7 @@ describe('dropdownToggle', function() {
281256
$rootScope.isopen = true;
282257
$rootScope.$digest();
283258
expect(isFocused(element.find('a'))).toBe(true);
259+
element.remove();
284260
});
285261
});
286262

@@ -420,6 +396,7 @@ describe('dropdownToggle', function() {
420396
triggerKeyDown($document, 27);
421397
expect(element.hasClass('open')).toBe(false);
422398
expect(isFocused(element.find('a'))).toBe(true);
399+
element.remove();
423400
});
424401

425402
it('should close anyway if another dropdown is opened', function() {

0 commit comments

Comments
 (0)