From 9247f15b30567a1f97e1dafad77f80f802d660b9 Mon Sep 17 00:00:00 2001 From: Robin van Baalen Date: Wed, 3 Jun 2015 12:11:59 -0400 Subject: [PATCH 1/9] docs(tooltip): add notice about deprecated feature Added a note that `tooltip-html-unsafe` is deprecated in favour of `tooltip-html` Closes #3634 --- src/tooltip/docs/readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tooltip/docs/readme.md b/src/tooltip/docs/readme.md index fcea6c11b0..78902756e3 100644 --- a/src/tooltip/docs/readme.md +++ b/src/tooltip/docs/readme.md @@ -7,10 +7,10 @@ There are three versions of the tooltip: `tooltip`, `tooltip-template`, and - `tooltip` takes text only and will escape any HTML provided. - `tooltip-template` takes text that specifies the location of a template to use for the tooltip. -- `tooltip-html-unsafe` takes - whatever HTML is provided and displays it in a tooltip; it's called "unsafe" - because the HTML is not sanitized. *The user is responsible for ensuring the +- `tooltip-html` takes + whatever HTML is provided and displays it in a tooltip; *The user is responsible for ensuring the content is safe to put into the DOM!* +- `tooltip-html-unsafe` -- deprecated in favour of `tooltip-html` The tooltip directives provide several optional attributes to control how they will display: From e5a1e88fd7f31572d4fadbab623bded4a0f89d71 Mon Sep 17 00:00:00 2001 From: CloudNiner Date: Sat, 23 May 2015 21:39:57 -0400 Subject: [PATCH 2/9] fix(dropdown): do not close on $locationChangeSuccess Behaviour only triggers when `auto-close=disabled` Closes #3683, #3704 --- src/dropdown/docs/readme.md | 3 +-- src/dropdown/dropdown.js | 4 +++- src/dropdown/test/dropdown.spec.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/dropdown/docs/readme.md b/src/dropdown/docs/readme.md index 02970d0a5f..47851ea1a3 100644 --- a/src/dropdown/docs/readme.md +++ b/src/dropdown/docs/readme.md @@ -10,5 +10,4 @@ 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. diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index 8f03186160..de5cba6d8d 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -144,7 +144,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() { diff --git a/src/dropdown/test/dropdown.spec.js b/src/dropdown/test/dropdown.spec.js index 047ca09720..75ab9fa7c2 100644 --- a/src/dropdown/test/dropdown.spec.js +++ b/src/dropdown/test/dropdown.spec.js @@ -432,5 +432,15 @@ describe('dropdownToggle', function() { expect(elm1.hasClass(dropdownConfig.openClass)).toBe(false); expect(elm2.hasClass(dropdownConfig.openClass)).toBe(true); }); + + it('should not close on $locationChangeSuccess if auto-close="disabled"', function () { + var elm1 = dropdown('disabled'); + expect(elm1.hasClass(dropdownConfig.openClass)).toBe(false); + clickDropdownToggle(elm1); + expect(elm1.hasClass(dropdownConfig.openClass)).toBe(true); + $rootScope.$broadcast('$locationChangeSuccess'); + $rootScope.$digest(); + expect(elm1.hasClass(dropdownConfig.openClass)).toBe(true); + }); }); }); From 195e520ec49a09514e2200f75fff99288d88f164 Mon Sep 17 00:00:00 2001 From: Scotty Waggoner Date: Mon, 11 May 2015 21:57:12 -0700 Subject: [PATCH 3/9] fix(typeahead): add href to show cursor as pointer When hovering over typeahead matches, the cursor is now shown as a pointer. Fixes #3649 --- template/typeahead/typeahead-match.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/typeahead/typeahead-match.html b/template/typeahead/typeahead-match.html index d79e10a18f..58b882e70b 100644 --- a/template/typeahead/typeahead-match.html +++ b/template/typeahead/typeahead-match.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From c946509bda9c24884fa39017bb3664c544b399fa Mon Sep 17 00:00:00 2001 From: marwy Date: Mon, 18 May 2015 18:55:35 +0200 Subject: [PATCH 4/9] docs(alert): document dismiss-on-timeout attribute --- src/alert/docs/readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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. From 10c67e7b5d938070ec45300ae9e20e235b8a86d2 Mon Sep 17 00:00:00 2001 From: Robin van Baalen Date: Thu, 4 Jun 2015 13:41:05 -0400 Subject: [PATCH 5/9] chore(license): update copyright year range --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 8297244aba1f00bc5ade125f2aaa4c024a09ab84 Mon Sep 17 00:00:00 2001 From: Robin van Baalen Date: Thu, 4 Jun 2015 13:49:52 -0400 Subject: [PATCH 6/9] docs(modal): fix markup --- src/modal/docs/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal/docs/readme.md b/src/modal/docs/readme.md index 1f60a009da..573b2510f6 100644 --- a/src/modal/docs/readme.md +++ b/src/modal/docs/readme.md @@ -23,7 +23,7 @@ The `open` method returns a modal instance, an object with the following propert * `dismiss(reason)` - a method that can be used to dismiss a modal, passing a reason * `result` - a promise that is resolved when a modal is closed and rejected when a modal is dismissed * `opened` - a promise that is resolved when a modal gets opened after downloading content's template and resolving all variables -* 'rendered' - a promise that is resolved when a modal is rendered. +* `rendered` - a promise that is resolved when a modal is rendered. In addition the scope associated with modal's content is augmented with 2 methods: From d631af5a05a692ce9781f61caa38fef60bb0c4a4 Mon Sep 17 00:00:00 2001 From: Rob Jacobs Date: Sat, 18 Oct 2014 09:21:53 -0400 Subject: [PATCH 7/9] fix(alert): rename alert-dismissable to alert-dismissible The use of alert-dismissable is now deprecated in correspondence with https://github.com/twbs/bootstrap/pull/13845 --- src/alert/test/alert.spec.js | 8 ++++---- template/alert/alert.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) 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('No close')(scope); scope.$digest(); expect(findCloseButton(0)).toBeHidden(); - expect(element).not.toHaveClass('alert-dismissable'); + expect(element).not.toHaveClass('alert-dismissible'); }); it('should be possible to add additional classes for alert', function () { diff --git a/template/alert/alert.html b/template/alert/alert.html index 6415960996..c813624858 100644 --- a/template/alert/alert.html +++ b/template/alert/alert.html @@ -1,4 +1,4 @@ - diff --git a/src/dropdown/docs/readme.md b/src/dropdown/docs/readme.md index 47851ea1a3..8bfc8cf2f5 100644 --- a/src/dropdown/docs/readme.md +++ b/src/dropdown/docs/readme.md @@ -11,3 +11,7 @@ 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. 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 de5cba6d8d..816629c98c 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -60,9 +60,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, @@ -131,9 +132,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 ); } @@ -168,10 +189,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 75ab9fa7c2..fc99695dbf 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('
  • ')($rootScope); + } + + beforeEach(function() { + element = dropdown(); + }); + + it('should apply custom template for dropdown menu', function() { + element.find('a').click(); + expect(element.find('ul.dropdown-menu').eq(0).find('li').eq(0).text()).toEqual('Item 1'); + }); + + it('should clear ul when dropdown menu is closed', function() { + element.find('a').click(); + expect(element.find('ul.dropdown-menu').eq(0).find('li').eq(0).text()).toEqual('Item 1'); + element.find('a').click(); + expect(element.find('ul.dropdown-menu').eq(0).find('li').length).toEqual(0); + }); + }); describe('using dropdown-append-to-body', function() { function dropdown() {