Skip to content

Commit b186945

Browse files
committed
chore(merge): Sync with master
# Conflicts: # src/dropdown/docs/demo.html # src/dropdown/dropdown.js
2 parents 6e38f72 + 83c4266 commit b186945

File tree

14 files changed

+140
-45
lines changed

14 files changed

+140
-45
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License
22

3-
Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
3+
Copyright (c) 2012-2015 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

src/alert/docs/readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ Alert is an AngularJS-version of bootstrap's alert.
22

33
This directive can be used to generate alerts from the dynamic model data (using the `ng-repeat` directive);
44

5-
The presence of the `close` attribute determines if a close button is displayed
5+
The presence of the `close` attribute determines if a close button is displayed.
6+
7+
The optional `dismiss-on-timeout` attribute takes the number of milliseconds that specify timeout duration, after which the alert will be closed.

src/alert/test/alert.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ describe('alert', function () {
6868
}
6969
});
7070

71-
it('should show close buttons and have the dismissable class', function () {
71+
it('should show close buttons and have the dismissible class', function () {
7272
var alerts = createAlerts();
7373

7474
for (var i = 0, n = alerts.length; i < n; i++) {
7575
expect(findCloseButton(i).css('display')).not.toBe('none');
76-
expect(alerts.eq(i)).toHaveClass('alert-dismissable');
76+
expect(alerts.eq(i)).toHaveClass('alert-dismissible');
7777
}
7878
});
7979

@@ -91,11 +91,11 @@ describe('alert', function () {
9191
expect(scope.removeAlert).toHaveBeenCalledWith(1);
9292
});
9393

94-
it('should not show close button and have the dismissable class if no close callback specified', function () {
94+
it('should not show close button and have the dismissible class if no close callback specified', function () {
9595
element = $compile('<alert>No close</alert>')(scope);
9696
scope.$digest();
9797
expect(findCloseButton(0)).toBeHidden();
98-
expect(element).not.toHaveClass('alert-dismissable');
98+
expect(element).not.toHaveClass('alert-dismissible');
9999
});
100100

101101
it('should be possible to add additional classes for alert', function () {

src/dropdown/docs/demo.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@
5656
</ul>
5757
</div>
5858

59+
<!-- Single button using template-url -->
60+
<div class="btn-group" dropdown>
61+
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle ng-disabled="disabled">
62+
Dropdown using template <span class="caret"></span>
63+
</button>
64+
<ul class="dropdown-menu" template-url="dropdown.html">
65+
</ul>
66+
</div>
67+
5968
<hr />
6069
<p>
6170
<button type="button" class="btn btn-default btn-sm" ng-click="toggleDropdown($event)">Toggle button dropdown</button>
@@ -77,4 +86,13 @@
7786
</ul>
7887
</div>
7988

89+
<script type="text/ng-template" id="dropdown.html">
90+
<ul class="dropdown-menu" role="menu">
91+
<li><a href="#">Action in Template</a></li>
92+
<li><a href="#">Another action in Template</a></li>
93+
<li><a href="#">Something else here</a></li>
94+
<li class="divider"></li>
95+
<li><a href="#">Separated link in Template</a></li>
96+
</ul>
97+
</script>
8098
</div>

src/dropdown/docs/readme.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@ By default the dropdown will automatically close if any of its elements is click
1212

1313
* `always` - (Default) automatically closes the dropdown when any of its elements is clicked.
1414
* `outsideClick` - closes the dropdown automatically only when the user clicks any element outside the dropdown.
15-
* `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.
15+
* `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. The dropdown will no longer close on `$locationChangeSuccess` events.
1616

17+
Optionally, you may specify a template for the dropdown menu using the `template-url` attribute. This is especially useful when you have multiple similar dropdowns in a repeater and you want to keep your HTML output lean and your number of scopes to a minimum. The template has full access to the scope in which the dropdown lies.
18+
19+
Example: `<ul class="dropdown-menu" template-url="custom-dropdown.html"></ul>`.

src/dropdown/dropdown.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
6565
};
6666
}])
6767

68-
.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) {
68+
.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', '$compile', '$templateRequest', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) {
6969
var self = this,
7070
scope = $scope.$new(), // create a child scope so we are not polluting original one
71+
templateScope,
7172
openClass = dropdownConfig.openClass,
7273
getIsOpen,
7374
setIsOpen = angular.noop,
@@ -173,9 +174,29 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
173174
$animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);
174175

175176
if ( isOpen ) {
177+
if (self.dropdownMenuTemplateUrl) {
178+
$templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {
179+
templateScope = scope.$new();
180+
$compile(tplContent.trim())(templateScope, function(dropdownElement) {
181+
var newEl = dropdownElement;
182+
self.dropdownMenu.replaceWith(newEl);
183+
self.dropdownMenu = newEl;
184+
});
185+
});
186+
}
187+
176188
scope.focusToggleElement();
177189
dropdownService.open( scope );
178190
} else {
191+
if (self.dropdownMenuTemplateUrl) {
192+
if (templateScope) {
193+
templateScope.$destroy();
194+
}
195+
var newEl = angular.element('<ul class="dropdown-menu"></ul>');
196+
self.dropdownMenu.replaceWith(newEl);
197+
self.dropdownMenu = newEl;
198+
}
199+
179200
dropdownService.close( scope );
180201
self.selectedOption = null;
181202
}
@@ -187,7 +208,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
187208
});
188209

189210
$scope.$on('$locationChangeSuccess', function() {
190-
scope.isOpen = false;
211+
if (scope.getAutoClose() !== 'disabled') {
212+
scope.isOpen = false;
213+
}
191214
});
192215

193216
$scope.$on('$destroy', function() {
@@ -209,10 +232,16 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
209232
restrict: 'AC',
210233
require: '?^dropdown',
211234
link: function(scope, element, attrs, dropdownCtrl) {
212-
if ( !dropdownCtrl ) {
235+
if (!dropdownCtrl) {
213236
return;
214237
}
215-
dropdownCtrl.dropdownMenu = element;
238+
var tplUrl = attrs.templateUrl;
239+
if (tplUrl) {
240+
dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
241+
}
242+
if (!dropdownCtrl.dropdownMenu) {
243+
dropdownCtrl.dropdownMenu = element;
244+
}
216245
}
217246
};
218247
})

src/dropdown/test/dropdown.spec.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
describe('dropdownToggle', function() {
2-
var $compile, $rootScope, $document, dropdownConfig, element;
2+
var $compile, $rootScope, $document, $templateCache, dropdownConfig, element;
33

44
beforeEach(module('ui.bootstrap.dropdown'));
55

6-
beforeEach(inject(function(_$compile_, _$rootScope_, _$document_, _dropdownConfig_) {
6+
beforeEach(inject(function(_$compile_, _$rootScope_, _$document_, _$templateCache_, _dropdownConfig_) {
77
$compile = _$compile_;
88
$rootScope = _$rootScope_;
99
$document = _$document_;
10+
$templateCache = _$templateCache_;
1011
dropdownConfig = _dropdownConfig_;
1112
}));
1213

@@ -182,6 +183,30 @@ describe('dropdownToggle', function() {
182183
expect(element.hasClass(dropdownConfig.openClass)).toBe(false);
183184
});
184185
});
186+
187+
describe('using dropdownMenuTemplate', function() {
188+
function dropdown() {
189+
$templateCache.put('custom.html', '<ul class="dropdown-menu"><li>Item 1</li></ul>');
190+
191+
return $compile('<li dropdown><a href dropdown-toggle></a><ul class="dropdown-menu" template-url="custom.html"></ul></li>')($rootScope);
192+
}
193+
194+
beforeEach(function() {
195+
element = dropdown();
196+
});
197+
198+
it('should apply custom template for dropdown menu', function() {
199+
element.find('a').click();
200+
expect(element.find('ul.dropdown-menu').eq(0).find('li').eq(0).text()).toEqual('Item 1');
201+
});
202+
203+
it('should clear ul when dropdown menu is closed', function() {
204+
element.find('a').click();
205+
expect(element.find('ul.dropdown-menu').eq(0).find('li').eq(0).text()).toEqual('Item 1');
206+
element.find('a').click();
207+
expect(element.find('ul.dropdown-menu').eq(0).find('li').length).toEqual(0);
208+
});
209+
});
185210

186211
describe('using dropdown-append-to-body', function() {
187212
function dropdown() {
@@ -432,6 +457,16 @@ describe('dropdownToggle', function() {
432457
expect(elm1.hasClass(dropdownConfig.openClass)).toBe(false);
433458
expect(elm2.hasClass(dropdownConfig.openClass)).toBe(true);
434459
});
460+
461+
it('should not close on $locationChangeSuccess if auto-close="disabled"', function () {
462+
var elm1 = dropdown('disabled');
463+
expect(elm1.hasClass(dropdownConfig.openClass)).toBe(false);
464+
clickDropdownToggle(elm1);
465+
expect(elm1.hasClass(dropdownConfig.openClass)).toBe(true);
466+
$rootScope.$broadcast('$locationChangeSuccess');
467+
$rootScope.$digest();
468+
expect(elm1.hasClass(dropdownConfig.openClass)).toBe(true);
469+
});
435470
});
436471

437472
describe('`keyboard-nav` option', function() {

src/modal/docs/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The `open` method returns a modal instance, an object with the following propert
2323
* `dismiss(reason)` - a method that can be used to dismiss a modal, passing a reason
2424
* `result` - a promise that is resolved when a modal is closed and rejected when a modal is dismissed
2525
* `opened` - a promise that is resolved when a modal gets opened after downloading content's template and resolving all variables
26-
* 'rendered' - a promise that is resolved when a modal is rendered.
26+
* `rendered` - a promise that is resolved when a modal is rendered.
2727

2828
In addition the scope associated with modal's content is augmented with 2 methods:
2929

src/timepicker/docs/readme.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ All settings can be provided as attributes in the `<timepicker>` or globally con
3535
* `arrowkeys`
3636
_(Defaults: true)_ :
3737
Whether user can use up/down arrowkeys inside the hours & minutes input to increase or decrease it's values.
38+
39+
* `show-spinners`
40+
_(Defaults: true)_ :
41+
Shows spinner arrows above and below the inputs

src/timepicker/timepicker.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ angular.module('ui.bootstrap.timepicker', [])
77
meridians: null,
88
readonlyInput: false,
99
mousewheel: true,
10-
arrowkeys: true
10+
arrowkeys: true,
11+
showSpinners: true
1112
})
1213

1314
.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {
@@ -258,7 +259,10 @@ angular.module('ui.bootstrap.timepicker', [])
258259
selected.setHours( dt.getHours(), dt.getMinutes() );
259260
refresh();
260261
}
261-
262+
263+
$scope.showSpinners = angular.isDefined($attrs.showSpinners) ?
264+
$scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;
265+
262266
$scope.incrementHours = function() {
263267
addMinutes( hourStep * 60 );
264268
};

src/tooltip/docs/readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ There are three versions of the tooltip: `tooltip`, `tooltip-template`, and
77
- `tooltip` takes text only and will escape any HTML provided.
88
- `tooltip-template` takes text that specifies the location of a template to
99
use for the tooltip.
10-
- `tooltip-html-unsafe` takes
11-
whatever HTML is provided and displays it in a tooltip; it's called "unsafe"
12-
because the HTML is not sanitized. *The user is responsible for ensuring the
10+
- `tooltip-html` takes
11+
whatever HTML is provided and displays it in a tooltip; *The user is responsible for ensuring the
1312
content is safe to put into the DOM!*
13+
- `tooltip-html-unsafe` -- deprecated in favour of `tooltip-html`
1414

1515
The tooltip directives provide several optional attributes to control how they
1616
will display:

template/alert/alert.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="alert" ng-class="['alert-' + (type || 'warning'), closeable ? 'alert-dismissable' : null]" role="alert">
1+
<div class="alert" ng-class="['alert-' + (type || 'warning'), closeable ? 'alert-dismissible' : null]" role="alert">
22
<button ng-show="closeable" type="button" class="close" ng-click="close()">
33
<span aria-hidden="true">&times;</span>
44
<span class="sr-only">Close</span>

template/timepicker/timepicker.html

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
<table>
2-
<tbody>
3-
<tr class="text-center">
4-
<td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
5-
<td>&nbsp;</td>
6-
<td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
7-
<td ng-show="showMeridian"></td>
8-
</tr>
9-
<tr>
10-
<td class="form-group" ng-class="{'has-error': invalidHours}">
11-
<input style="width:50px;" type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">
12-
</td>
13-
<td>:</td>
14-
<td class="form-group" ng-class="{'has-error': invalidMinutes}">
15-
<input style="width:50px;" type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">
16-
</td>
17-
<td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>
18-
</tr>
19-
<tr class="text-center">
20-
<td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
21-
<td>&nbsp;</td>
22-
<td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
23-
<td ng-show="showMeridian"></td>
24-
</tr>
25-
</tbody>
2+
<tbody>
3+
<tr class="text-center" ng-show="showSpinners">
4+
<td><a ng-click="incrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
5+
<td>&nbsp;</td>
6+
<td><a ng-click="incrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
7+
<td ng-show="showMeridian"></td>
8+
</tr>
9+
<tr>
10+
<td class="form-group" ng-class="{'has-error': invalidHours}">
11+
<input style="width:50px;" type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">
12+
</td>
13+
<td>:</td>
14+
<td class="form-group" ng-class="{'has-error': invalidMinutes}">
15+
<input style="width:50px;" type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2">
16+
</td>
17+
<td ng-show="showMeridian"><button type="button" class="btn btn-default text-center" ng-click="toggleMeridian()">{{meridian}}</button></td>
18+
</tr>
19+
<tr class="text-center" ng-show="::showSpinners">
20+
<td><a ng-click="decrementHours()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
21+
<td>&nbsp;</td>
22+
<td><a ng-click="decrementMinutes()" class="btn btn-link"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
23+
<td ng-show="showMeridian"></td>
24+
</tr>
25+
</tbody>
2626
</table>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<a tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>
1+
<a href="javascript:void(0)" tabindex="-1" bind-html-unsafe="match.label | typeaheadHighlight:query"></a>

0 commit comments

Comments
 (0)