From f02a24d2323b75cc35c014919ebe0a03be548c7a Mon Sep 17 00:00:00 2001
From: Robin van Baalen
Date: Sun, 7 Jun 2015 22:33:31 -0400
Subject: [PATCH 0001/1156] chore(readme): make main title fit on one line
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4a4d595d91..028c59551b 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)
+### UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)
[](https://gitter.im/angular-ui/bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](http://travis-ci.org/angular-ui/bootstrap)
From 115d490a251a557828ecc24e12367abc5ef009c5 Mon Sep 17 00:00:00 2001
From: Wesley Cho
Date: Tue, 9 Jun 2015 23:23:11 -0700
Subject: [PATCH 0002/1156] fix(carousel): ensure there are slides present
- Ensure there are slides present before calling `$scope.next` in timer
Fixes #3755
---
src/carousel/carousel.js | 2 +-
src/carousel/test/carousel.spec.js | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/carousel/carousel.js b/src/carousel/carousel.js
index ce50c9429a..8fc66e5ef8 100644
--- a/src/carousel/carousel.js
+++ b/src/carousel/carousel.js
@@ -113,7 +113,7 @@ angular.module('ui.bootstrap.carousel', [])
function timerFn() {
var interval = +$scope.interval;
- if (isPlaying && !isNaN(interval) && interval > 0) {
+ if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {
$scope.next();
} else {
$scope.pause();
diff --git a/src/carousel/test/carousel.spec.js b/src/carousel/test/carousel.spec.js
index 86e5a0735a..82a878d659 100644
--- a/src/carousel/test/carousel.spec.js
+++ b/src/carousel/test/carousel.spec.js
@@ -146,7 +146,7 @@ describe('carousel', function() {
testSlideActive(1);
});
- it('shouldnt go forward if interval is NaN or negative', function() {
+ it('shouldnt go forward if interval is NaN or negative or has no slides', function() {
testSlideActive(0);
var previousInterval = scope.interval;
scope.$apply('interval = -1');
@@ -161,6 +161,9 @@ describe('carousel', function() {
scope.$apply('interval = 1000');
$interval.flush(1000);
testSlideActive(2);
+ scope.$apply('slides = []');
+ $interval.flush(1000);
+ testSlideActive(2);
});
it('should bind the content to slides', function() {
From 0d96221fa32794deb702d1b923ae38f11f5b66a4 Mon Sep 17 00:00:00 2001
From: Wesley Cho
Date: Wed, 10 Jun 2015 06:48:49 -0700
Subject: [PATCH 0003/1156] fix(typeahead): do not execute unnecessary $digest
- If in a $digest, do not execute `scope.$digest`
Fixes #2652
Closes #3791
---
src/typeahead/typeahead.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/typeahead/typeahead.js b/src/typeahead/typeahead.js
index 1fe28401ab..994a7b2e79 100644
--- a/src/typeahead/typeahead.js
+++ b/src/typeahead/typeahead.js
@@ -29,8 +29,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
};
}])
- .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',
- function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {
+ .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$rootScope', '$position', 'typeaheadParser',
+ function ($compile, $parse, $q, $timeout, $document, $rootScope, $position, typeaheadParser) {
var HOT_KEYS = [9, 13, 27, 38, 40];
@@ -318,7 +318,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
var dismissClickHandler = function (evt) {
if (element[0] !== evt.target) {
resetMatches();
- scope.$digest();
+ if (!$rootScope.$$phase) {
+ scope.$digest();
+ }
}
};
From 988336ccff6efccc88bd26b8015d79d4a82c229c Mon Sep 17 00:00:00 2001
From: Thomas Haukland
Date: Mon, 11 May 2015 23:46:50 +0200
Subject: [PATCH 0004/1156] fix(modal): focus on body if element disappears
- Change to focus on `document.body` instead if element is not present
Closes #3653
Fixes #3639
---
src/modal/modal.js | 15 ++++++++++-----
src/modal/test/modal.spec.js | 26 +++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/src/modal/modal.js b/src/modal/modal.js
index 9470f62d5c..c6215f4a11 100644
--- a/src/modal/modal.js
+++ b/src/modal/modal.js
@@ -195,7 +195,7 @@ angular.module('ui.bootstrap.modal', [])
}
});
- function removeModalWindow(modalInstance) {
+ function removeModalWindow(modalInstance, elementToReceiveFocus) {
var body = $document.find('body').eq(0);
var modalWindow = openedWindows.get(modalInstance).value;
@@ -208,6 +208,13 @@ angular.module('ui.bootstrap.modal', [])
body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
checkRemoveBackdrop();
});
+
+ //move focus to specified element if available, or else to body
+ if (elementToReceiveFocus && elementToReceiveFocus.focus) {
+ elementToReceiveFocus.focus();
+ } else {
+ body.focus();
+ }
}
function checkRemoveBackdrop() {
@@ -318,8 +325,7 @@ angular.module('ui.bootstrap.modal', [])
var modalWindow = openedWindows.get(modalInstance);
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
modalWindow.value.deferred.resolve(result);
- removeModalWindow(modalInstance);
- modalWindow.value.modalOpener.focus();
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
return true;
}
return !modalWindow;
@@ -329,8 +335,7 @@ angular.module('ui.bootstrap.modal', [])
var modalWindow = openedWindows.get(modalInstance);
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
modalWindow.value.deferred.reject(reason);
- removeModalWindow(modalInstance);
- modalWindow.value.modalOpener.focus();
+ removeModalWindow(modalInstance, modalWindow.value.modalOpener);
return true;
}
return !modalWindow;
diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js
index c1d5fe4c29..0afe94ab8d 100644
--- a/src/modal/test/modal.spec.js
+++ b/src/modal/test/modal.spec.js
@@ -250,7 +250,7 @@ describe('$modal', function () {
expect($document).toHaveModalsOpen(0);
});
- it('should return to the element which had focus before the dialog is invoked', function () {
+ it('should return to the element which had focus before the dialog was invoked', function () {
var link = 'Link';
var element = angular.element(link);
angular.element(document.body).append(element);
@@ -272,6 +272,30 @@ describe('$modal', function () {
element.remove();
});
+ it('should return to document.body if element which had focus before the dialog was invoked is gone, or is missing focus function', function () {
+ var link = 'Link';
+ var element = angular.element(link);
+ angular.element(document.body).append(element);
+ element.focus();
+ expect(document.activeElement.tagName).toBe('A');
+
+ var modal = open({template: 'Content
'});
+ $timeout.flush();
+ expect(document.activeElement.tagName).toBe('DIV');
+ expect($document).toHaveModalsOpen(1);
+
+ // Fake undefined focus function, happening in IE in certain
+ // iframe conditions. See issue 3639
+ element[0].focus = undefined;
+ triggerKeyDown($document, 27);
+ $timeout.flush();
+ $rootScope.$digest();
+
+ expect(document.activeElement.tagName).toBe('BODY');
+ expect($document).toHaveModalsOpen(0);
+ element.remove();
+ });
+
it('should resolve returned promise on close', function () {
var modal = open({template: 'Content
'});
close(modal, 'closed ok');
From a5a25141fc88e642b84e135796daaf77dc653273 Mon Sep 17 00:00:00 2001
From: Joe Ibershoff
Date: Wed, 29 Apr 2015 20:26:56 -0400
Subject: [PATCH 0005/1156] feat(typeahead): handles min-length of 0
Closes #3600
---
src/typeahead/test/typeahead.spec.js | 9 +++++++++
src/typeahead/typeahead.js | 7 +++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/typeahead/test/typeahead.spec.js b/src/typeahead/test/typeahead.spec.js
index 741621e65c..a86dcedd7e 100644
--- a/src/typeahead/test/typeahead.spec.js
+++ b/src/typeahead/test/typeahead.spec.js
@@ -842,4 +842,13 @@ describe('typeahead tests', function () {
expect($scope.select_count).toEqual(1);
});
+ describe('minLength set to 0', function () {
+ it('should open typeahead if input is changed to empty string if defined threshold is 0', function () {
+ var element = prepareInputEl('');
+ changeInputValueTo(element, '');
+
+ expect(element).toBeOpenWithActive(3, 0);
+ });
+ });
+
});
diff --git a/src/typeahead/typeahead.js b/src/typeahead/typeahead.js
index 994a7b2e79..b1efde2409 100644
--- a/src/typeahead/typeahead.js
+++ b/src/typeahead/typeahead.js
@@ -41,7 +41,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
//SUPPORTED ATTRIBUTES (OPTIONS)
//minimal no of characters that needs to be entered before typeahead kicks-in
- var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
+ var minLength = originalScope.$eval(attrs.typeaheadMinLength);
+ if (!minLength && minLength !== 0) {
+ minLength = 1;
+ }
//minimal wait time after last character typed before typeahead kicks-in
var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
@@ -193,7 +196,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
hasFocus = true;
- if (inputValue && inputValue.length >= minSearch) {
+ if (minLength === 0 || inputValue && inputValue.length >= minLength) {
if (waitTime > 0) {
cancelPreviousTimeout();
scheduleSearchWithTimeout(inputValue);
From ca07ad7c72faa9672376aaebc38d4b15ef436e9a Mon Sep 17 00:00:00 2001
From: Wesley Cho
Date: Wed, 10 Jun 2015 09:35:16 -0700
Subject: [PATCH 0006/1156] fix(carousel): change to avoid references to debug
info
- Change usage of `.scope()` and `.isolateScope()` to grab metadata from elements
Closes #3795
Fixes #3794
---
src/carousel/carousel.js | 20 +++++++++++++++-----
src/carousel/test/carousel.spec.js | 2 +-
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/carousel/carousel.js b/src/carousel/carousel.js
index 8fc66e5ef8..3b99a20052 100644
--- a/src/carousel/carousel.js
+++ b/src/carousel/carousel.js
@@ -7,9 +7,11 @@
*
*/
angular.module('ui.bootstrap.carousel', [])
-.controller('CarouselController', ['$scope', '$interval', '$animate', function ($scope, $interval, $animate) {
+.controller('CarouselController', ['$scope', '$element', '$interval', '$animate', function ($scope, $element, $interval, $animate) {
var self = this,
slides = self.slides = $scope.slides = [],
+ NO_TRANSITION = 'uib-noTransition',
+ SLIDE_DIRECTION = 'uib-slideDirection',
currentIndex = -1,
currentInterval, isPlaying;
self.currentSlide = null;
@@ -36,6 +38,7 @@ angular.module('ui.bootstrap.carousel', [])
angular.extend(self.currentSlide || {}, {direction: direction, active: false});
if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition &&
slide.$element) {
+ slide.$element.data(SLIDE_DIRECTION, slide.direction);
$scope.$currentTransition = true;
slide.$element.one('$animate:close', function closeFn() {
$scope.$currentTransition = null;
@@ -167,6 +170,10 @@ angular.module('ui.bootstrap.carousel', [])
}
};
+ $scope.$watch('noTransition', function(noTransition) {
+ $element.data(NO_TRANSITION, noTransition);
+ });
+
}])
/**
@@ -295,13 +302,16 @@ function CarouselDemoCtrl($scope) {
.animation('.item', [
'$animate',
function ($animate) {
+ var NO_TRANSITION = 'uib-noTransition',
+ SLIDE_DIRECTION = 'uib-slideDirection';
+
return {
beforeAddClass: function (element, className, done) {
// Due to transclusion, noTransition property is on parent's scope
if (className == 'active' && element.parent() &&
- !element.parent().scope().noTransition) {
+ !element.parent().data(NO_TRANSITION)) {
var stopped = false;
- var direction = element.isolateScope().direction;
+ var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction == 'next' ? 'left' : 'right';
element.addClass(direction);
$animate.addClass(element, directionClass).then(function () {
@@ -320,9 +330,9 @@ function ($animate) {
beforeRemoveClass: function (element, className, done) {
// Due to transclusion, noTransition property is on parent's scope
if (className == 'active' && element.parent() &&
- !element.parent().scope().noTransition) {
+ !element.parent().data(NO_TRANSITION)) {
var stopped = false;
- var direction = element.isolateScope().direction;
+ var direction = element.data(SLIDE_DIRECTION);
var directionClass = direction == 'next' ? 'left' : 'right';
$animate.addClass(element, directionClass).then(function () {
if (!stopped) {
diff --git a/src/carousel/test/carousel.spec.js b/src/carousel/test/carousel.spec.js
index 82a878d659..69babfc071 100644
--- a/src/carousel/test/carousel.spec.js
+++ b/src/carousel/test/carousel.spec.js
@@ -349,7 +349,7 @@ describe('carousel', function() {
beforeEach(function() {
scope = $rootScope.$new();
- ctrl = $controller('CarouselController', {$scope: scope, $element: null});
+ ctrl = $controller('CarouselController', {$scope: scope, $element: angular.element('')});
for(var i = 0;i < slides.length;i++){
ctrl.addSlide(slides[i]);
}
From 49e73a89f36b1c44d7547b8910bcb17e96135294 Mon Sep 17 00:00:00 2001
From: Wesley Cho
Date: Thu, 11 Jun 2015 09:47:28 -0700
Subject: [PATCH 0007/1156] chore(typeahead): change to one-way binding for
position
- Change position to one-way binding to reduce an unnecessary $watch
chore(typeahead): add bind once to id attr
---
src/typeahead/typeahead.js | 2 +-
template/typeahead/typeahead-popup.html | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/typeahead/typeahead.js b/src/typeahead/typeahead.js
index b1efde2409..10b7778cf7 100644
--- a/src/typeahead/typeahead.js
+++ b/src/typeahead/typeahead.js
@@ -357,7 +357,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
matches:'=',
query:'=',
active:'=',
- position:'=',
+ position:'&',
select:'&'
},
replace:true,
diff --git a/template/typeahead/typeahead-popup.html b/template/typeahead/typeahead-popup.html
index e1bd0c1c47..9760c154b5 100644
--- a/template/typeahead/typeahead-popup.html
+++ b/template/typeahead/typeahead-popup.html
@@ -1,5 +1,5 @@
-
-
-
From 2332f14d661d5b2b676adbfbfcfd3374935cf81b Mon Sep 17 00:00:00 2001
From: Schmulik Raskin
Date: Wed, 8 Jul 2015 14:10:26 +0300
Subject: [PATCH 0032/1156] fix(dropdown): align when using dropdown-menu-body
- Fixes the right alignment when using the `dropdown-menu-body` class in
conjunction with the dropdown component
Closes #3913
Fixes #3820
---
src/dropdown/dropdown.js | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js
index e6b950e746..31a480e7fd 100644
--- a/src/dropdown/dropdown.js
+++ b/src/dropdown/dropdown.js
@@ -162,13 +162,23 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
};
scope.$watch('isOpen', function( isOpen, wasOpen ) {
- if ( appendToBody && self.dropdownMenu ) {
- var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true);
- self.dropdownMenu.css({
- top: pos.top + 'px',
- left: pos.left + 'px',
- display: isOpen ? 'block' : 'none'
- });
+ if (appendToBody && self.dropdownMenu) {
+ var pos = $position.positionElements(self.$element, self.dropdownMenu, 'bottom-left', true);
+ var css = {
+ top: pos.top + 'px',
+ display: isOpen ? 'block' : 'none'
+ };
+
+ var rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');
+ if (!rightalign) {
+ css.left = pos.left + 'px';
+ css.right = 'auto';
+ } else {
+ css.left = 'auto';
+ css.right = (window.innerWidth - (pos.left + self.$element.prop('offsetWidth'))) + 'px';
+ }
+
+ self.dropdownMenu.css(css);
}
$animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass).then(function() {
From 4af83ade14911ce9d8c3d494a4d166e5fab19ed9 Mon Sep 17 00:00:00 2001
From: Brian
Date: Tue, 21 Jul 2015 13:12:30 -0600
Subject: [PATCH 0033/1156] feat(dropdown): add dropdown classes dynamically
- Add `dropdown` and `dropdown-toggle` classes dynamically for template simplification
Closes #3984
Closes #3986
---
src/dropdown/docs/demo.html | 14 +++++++-------
src/dropdown/dropdown.js | 3 +++
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/dropdown/docs/demo.html b/src/dropdown/docs/demo.html
index 2e80a3c207..481cb75252 100644
--- a/src/dropdown/docs/demo.html
+++ b/src/dropdown/docs/demo.html
@@ -1,8 +1,8 @@