diff --git a/LICENSE b/LICENSE
index 638cdf29f4..18db5a5313 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License
-Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
+Copyright (c) 2012-2015 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/alert/docs/readme.md b/src/alert/docs/readme.md
index 0982c205ea..4bc6f5242c 100644
--- a/src/alert/docs/readme.md
+++ b/src/alert/docs/readme.md
@@ -2,4 +2,6 @@ Alert is an AngularJS-version of bootstrap's alert.
This directive can be used to generate alerts from the dynamic model data (using the `ng-repeat` directive);
-The presence of the `close` attribute determines if a close button is displayed
+The presence of the `close` attribute determines if a close button is displayed.
+
+The optional `dismiss-on-timeout` attribute takes the number of milliseconds that specify timeout duration, after which the alert will be closed.
diff --git a/src/alert/test/alert.spec.js b/src/alert/test/alert.spec.js
index fa0b4fb619..271833309a 100644
--- a/src/alert/test/alert.spec.js
+++ b/src/alert/test/alert.spec.js
@@ -68,12 +68,12 @@ describe('alert', function () {
}
});
- it('should show close buttons and have the dismissable class', function () {
+ it('should show close buttons and have the dismissible class', function () {
var alerts = createAlerts();
for (var i = 0, n = alerts.length; i < n; i++) {
expect(findCloseButton(i).css('display')).not.toBe('none');
- expect(alerts.eq(i)).toHaveClass('alert-dismissable');
+ expect(alerts.eq(i)).toHaveClass('alert-dismissible');
}
});
@@ -91,11 +91,11 @@ describe('alert', function () {
expect(scope.removeAlert).toHaveBeenCalledWith(1);
});
- it('should not show close button and have the dismissable class if no close callback specified', function () {
+ it('should not show close button and have the dismissible class if no close callback specified', function () {
element = $compile('
@@ -77,4 +86,13 @@ + diff --git a/src/dropdown/docs/readme.md b/src/dropdown/docs/readme.md index 6f1cb41810..ff94a1cca1 100644 --- a/src/dropdown/docs/readme.md +++ b/src/dropdown/docs/readme.md @@ -12,5 +12,8 @@ By default the dropdown will automatically close if any of its elements is click * `always` - (Default) automatically closes the dropdown when any of its elements is clicked. * `outsideClick` - closes the dropdown automatically only when the user clicks any element outside the dropdown. - * `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. + * `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. +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. + +Example: `
`. diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index 7e7befa985..3ad31095f8 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -65,9 +65,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) }; }]) -.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) { +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', '$compile', '$templateRequest', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) { var self = this, scope = $scope.$new(), // create a child scope so we are not polluting original one + templateScope, openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, @@ -173,9 +174,29 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); if ( isOpen ) { + if (self.dropdownMenuTemplateUrl) { + $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) { + templateScope = scope.$new(); + $compile(tplContent.trim())(templateScope, function(dropdownElement) { + var newEl = dropdownElement; + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; + }); + }); + } + scope.focusToggleElement(); dropdownService.open( scope ); } else { + if (self.dropdownMenuTemplateUrl) { + if (templateScope) { + templateScope.$destroy(); + } + var newEl = angular.element(' '); + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; + } + dropdownService.close( scope ); self.selectedOption = null; } @@ -187,7 +208,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) }); $scope.$on('$locationChangeSuccess', function() { - scope.isOpen = false; + if (scope.getAutoClose() !== 'disabled') { + scope.isOpen = false; + } }); $scope.$on('$destroy', function() { @@ -209,10 +232,16 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) restrict: 'AC', require: '?^dropdown', link: function(scope, element, attrs, dropdownCtrl) { - if ( !dropdownCtrl ) { + if (!dropdownCtrl) { return; } - dropdownCtrl.dropdownMenu = element; + var tplUrl = attrs.templateUrl; + if (tplUrl) { + dropdownCtrl.dropdownMenuTemplateUrl = tplUrl; + } + if (!dropdownCtrl.dropdownMenu) { + dropdownCtrl.dropdownMenu = element; + } } }; }) diff --git a/src/dropdown/test/dropdown.spec.js b/src/dropdown/test/dropdown.spec.js index 356a0a0930..686f27d52c 100644 --- a/src/dropdown/test/dropdown.spec.js +++ b/src/dropdown/test/dropdown.spec.js @@ -1,12 +1,13 @@ describe('dropdownToggle', function() { - var $compile, $rootScope, $document, dropdownConfig, element; + var $compile, $rootScope, $document, $templateCache, dropdownConfig, element; beforeEach(module('ui.bootstrap.dropdown')); - beforeEach(inject(function(_$compile_, _$rootScope_, _$document_, _dropdownConfig_) { + beforeEach(inject(function(_$compile_, _$rootScope_, _$document_, _$templateCache_, _dropdownConfig_) { $compile = _$compile_; $rootScope = _$rootScope_; $document = _$document_; + $templateCache = _$templateCache_; dropdownConfig = _dropdownConfig_; })); @@ -182,6 +183,30 @@ describe('dropdownToggle', function() { expect(element.hasClass(dropdownConfig.openClass)).toBe(false); }); }); + + describe('using dropdownMenuTemplate', function() { + function dropdown() { + $templateCache.put('custom.html', ' '); + + return $compile('