From 9d7f18344d4862f23a2b919d83914a6f4a3eec9e Mon Sep 17 00:00:00 2001 From: Rob Cresswell Date: Sat, 29 Oct 2016 12:49:29 +0200 Subject: Update XStatic-angular-bootstrap to 2.2.0.0 Change-Id: Idd53f42c841802af830864a5497e433c41628bd3 --- setup.cfg | 2 +- xstatic/pkg/angular_bootstrap/__init__.py | 4 +- .../angular_bootstrap/data/angular-bootstrap.js | 1001 +++++++++++++------- 3 files changed, 643 insertions(+), 364 deletions(-) diff --git a/setup.cfg b/setup.cfg index 288215c..0f43a6e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = XStatic-Angular-Bootstrap -description = Angular-Bootstrap 1.3.3 (XStatic packaging standard) +description = Angular-Bootstrap 2.2.0 (XStatic packaging standard) description-file = README.rst maintainer = Rob Cresswell maintainer-email = robert.cresswell@outlook.com diff --git a/xstatic/pkg/angular_bootstrap/__init__.py b/xstatic/pkg/angular_bootstrap/__init__.py index 9c0a7ae..ed1afdd 100644 --- a/xstatic/pkg/angular_bootstrap/__init__.py +++ b/xstatic/pkg/angular_bootstrap/__init__.py @@ -11,7 +11,7 @@ NAME = __name__.split('.')[-1] # package name (e.g. 'foo' or 'foo_bar') # please use a all-lowercase valid python # package name -VERSION = '1.3.3' # version of the packaged files, please use the upstream +VERSION = '2.2.0' # version of the packaged files, please use the upstream # version number BUILD = '0' # our package build number, so we can release new builds # with fixes for xstatic stuff. @@ -38,6 +38,8 @@ BASE_DIR = join(dirname(__file__), 'data') # linux package maintainers just can point to their file locations like this: #BASE_DIR = '/usr/share/javascript/angular_cookies' +MAIN='angular-bootstrap.js' + LOCATIONS = { # CDN locations (if no public CDN exists, use an empty dict) # if value is a string, it is a base location, just append relative diff --git a/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js b/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js index 918ef43..2ee890e 100644 --- a/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js +++ b/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js @@ -2,10 +2,10 @@ * angular-ui-bootstrap * http://angular-ui.github.io/bootstrap/ - * Version: 1.3.3 - 2016-05-22 + * Version: 2.2.0 - 2016-10-10 * License: MIT - */angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); -angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/backdrop.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]); + */angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); +angular.module("ui.bootstrap.tpls", ["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]); angular.module('ui.bootstrap.collapse', []) .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) { @@ -13,16 +13,42 @@ angular.module('ui.bootstrap.collapse', []) return { link: function(scope, element, attrs) { var expandingExpr = $parse(attrs.expanding), - expandedExpr = $parse(attrs.expanded), - collapsingExpr = $parse(attrs.collapsing), - collapsedExpr = $parse(attrs.collapsed); + expandedExpr = $parse(attrs.expanded), + collapsingExpr = $parse(attrs.collapsing), + collapsedExpr = $parse(attrs.collapsed), + horizontal = false, + css = {}, + cssTo = {}; + + init(); + + function init() { + horizontal = !!('horizontal' in attrs); + if (horizontal) { + css = { + width: '' + }; + cssTo = {width: '0'}; + } else { + css = { + height: '' + }; + cssTo = {height: '0'}; + } + if (!scope.$eval(attrs.uibCollapse)) { + element.addClass('in') + .addClass('collapse') + .attr('aria-expanded', true) + .attr('aria-hidden', false) + .css(css); + } + } - if (!scope.$eval(attrs.uibCollapse)) { - element.addClass('in') - .addClass('collapse') - .attr('aria-expanded', true) - .attr('aria-hidden', false) - .css({height: 'auto'}); + function getScrollFromElement(element) { + if (horizontal) { + return {width: element.scrollWidth + 'px'}; + } + return {height: element.scrollHeight + 'px'}; } function expand() { @@ -41,11 +67,17 @@ angular.module('ui.bootstrap.collapse', []) $animateCss(element, { addClass: 'in', easing: 'ease', - to: { height: element[0].scrollHeight + 'px' } + css: { + overflow: 'hidden' + }, + to: getScrollFromElement(element[0]) }).start()['finally'](expandDone); } else { $animate.addClass(element, 'in', { - to: { height: element[0].scrollHeight + 'px' } + css: { + overflow: 'hidden' + }, + to: getScrollFromElement(element[0]) }).then(expandDone); } }); @@ -54,7 +86,7 @@ angular.module('ui.bootstrap.collapse', []) function expandDone() { element.removeClass('collapsing') .addClass('collapse') - .css({height: 'auto'}); + .css(css); expandedExpr(scope); } @@ -66,10 +98,10 @@ angular.module('ui.bootstrap.collapse', []) $q.resolve(collapsingExpr(scope)) .then(function() { element - // IMPORTANT: The height must be set before adding "collapsing" class. - // Otherwise, the browser attempts to animate from height 0 (in - // collapsing class) to the given height here. - .css({height: element[0].scrollHeight + 'px'}) + // IMPORTANT: The width must be set before adding "collapsing" class. + // Otherwise, the browser attempts to animate from width 0 (in + // collapsing class) to the given width here. + .css(getScrollFromElement(element[0])) // initially all panel collapse have the collapse class, this removal // prevents the animation from jumping to collapsed state .removeClass('collapse') @@ -80,18 +112,18 @@ angular.module('ui.bootstrap.collapse', []) if ($animateCss) { $animateCss(element, { removeClass: 'in', - to: {height: '0'} + to: cssTo }).start()['finally'](collapseDone); } else { $animate.removeClass(element, 'in', { - to: {height: '0'} + to: cssTo }).then(collapseDone); } }); } function collapseDone() { - element.css({height: '0'}); // Required so that collapse works when animation is disabled + element.css(cssTo); // Required so that collapse works when animation is disabled element.removeClass('collapsing') .addClass('collapse'); collapsedExpr(scope); @@ -108,7 +140,20 @@ angular.module('ui.bootstrap.collapse', []) }; }]); -angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) +angular.module('ui.bootstrap.tabindex', []) + +.directive('uibTabindexToggle', function() { + return { + restrict: 'A', + link: function(scope, elem, attrs) { + attrs.$observe('disabled', function(disabled) { + attrs.$set('tabindex', disabled ? -1 : null); + }); + } + }; +}); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex']) .constant('uibAccordionConfig', { closeOthers: true @@ -168,7 +213,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) return { require: '^uibAccordion', // We need this directive to be inside an accordion transclude: true, // It transcludes the contents of the directive into the template - replace: true, // The element containing the directive will be replaced with the template + restrict: 'A', templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/accordion/accordion-group.html'; }, @@ -184,6 +229,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) }; }, link: function(scope, element, attrs, accordionCtrl) { + element.addClass('panel'); accordionCtrl.addGroup(scope); scope.openClass = attrs.openClass || 'panel-open'; @@ -255,8 +301,13 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) angular.module('ui.bootstrap.alert', []) -.controller('UibAlertController', ['$scope', '$attrs', '$interpolate', '$timeout', function($scope, $attrs, $interpolate, $timeout) { +.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) { $scope.closeable = !!$attrs.close; + $element.addClass('alert'); + $attrs.$set('role', 'alert'); + if ($scope.closeable) { + $element.addClass('alert-dismissible'); + } var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ? $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null; @@ -272,13 +323,12 @@ angular.module('ui.bootstrap.alert', []) return { controller: 'UibAlertController', controllerAs: 'alert', + restrict: 'A', templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/alert/alert.html'; }, transclude: true, - replace: true, scope: { - type: '@', close: '&' } }; @@ -389,6 +439,7 @@ angular.module('ui.bootstrap.carousel', []) currentInterval, isPlaying, bufferedTransitions = []; var destroyed = false; + $element.addClass('carousel'); self.addSlide = function(slide, element) { slides.push({ @@ -526,6 +577,9 @@ angular.module('ui.bootstrap.carousel', []) } }; + $element.on('mouseenter', $scope.pause); + $element.on('mouseleave', $scope.play); + $scope.$on('$destroy', function() { destroyed = true; resetTimer(); @@ -661,9 +715,9 @@ angular.module('ui.bootstrap.carousel', []) .directive('uibCarousel', function() { return { transclude: true, - replace: true, controller: 'UibCarouselController', controllerAs: 'carousel', + restrict: 'A', templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/carousel/carousel.html'; }, @@ -677,11 +731,11 @@ angular.module('ui.bootstrap.carousel', []) }; }) -.directive('uibSlide', function() { +.directive('uibSlide', ['$animate', function($animate) { return { require: '^uibCarousel', + restrict: 'A', transclude: true, - replace: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/carousel/slide.html'; }, @@ -690,14 +744,19 @@ angular.module('ui.bootstrap.carousel', []) index: '=?' }, link: function (scope, element, attrs, carouselCtrl) { + element.addClass('item'); carouselCtrl.addSlide(scope, element); //when the scope is destroyed then remove the slide from the current slides array scope.$on('$destroy', function() { carouselCtrl.removeSlide(scope); }); + + scope.$watch('active', function(active) { + $animate[active ? 'addClass' : 'removeClass'](element, 'active'); + }); } }; -}) +}]) .animation('.item', ['$animateCss', function($animateCss) { @@ -986,7 +1045,7 @@ angular.module('ui.bootstrap.dateparser', []) this.init(); - function createParser(format, func) { + function createParser(format) { var map = [], regex = format.split(''); // check for literal values @@ -1035,7 +1094,7 @@ angular.module('ui.bootstrap.dateparser', []) map.push({ index: index, key: data.key, - apply: data[func], + apply: data.apply, matcher: data.regex }); } @@ -1047,6 +1106,70 @@ angular.module('ui.bootstrap.dateparser', []) }; } + function createFormatter(format) { + var formatters = []; + var i = 0; + var formatter, literalIdx; + while (i < format.length) { + if (angular.isNumber(literalIdx)) { + if (format.charAt(i) === '\'') { + if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') { + formatters.push(constructLiteralFormatter(format, literalIdx, i)); + literalIdx = null; + } + } else if (i === format.length) { + while (literalIdx < format.length) { + formatter = constructFormatterFromIdx(format, literalIdx); + formatters.push(formatter); + literalIdx = formatter.endIdx; + } + } + + i++; + continue; + } + + if (format.charAt(i) === '\'') { + literalIdx = i; + i++; + continue; + } + + formatter = constructFormatterFromIdx(format, i); + + formatters.push(formatter.parser); + i = formatter.endIdx; + } + + return formatters; + } + + function constructLiteralFormatter(format, literalIdx, endIdx) { + return function() { + return format.substr(literalIdx + 1, endIdx - literalIdx - 1); + }; + } + + function constructFormatterFromIdx(format, i) { + var currentPosStr = format.substr(i); + for (var j = 0; j < formatCodeToRegex.length; j++) { + if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) { + var data = formatCodeToRegex[j]; + return { + endIdx: i + data.key.length, + parser: data.formatter + }; + } + } + + return { + endIdx: i + 1, + parser: function() { + return currentPosStr.charAt(0); + } + }; + } + this.filter = function(date, format) { if (!angular.isDate(date) || isNaN(date) || !format) { return ''; @@ -1059,28 +1182,13 @@ angular.module('ui.bootstrap.dateparser', []) } if (!this.formatters[format]) { - this.formatters[format] = createParser(format, 'formatter'); + this.formatters[format] = createFormatter(format); } - var parser = this.formatters[format], - map = parser.map; - - var _format = format; + var formatters = this.formatters[format]; - return map.reduce(function(str, mapper, i) { - var match = _format.match(new RegExp('(.*)' + mapper.key)); - if (match && angular.isString(match[1])) { - str += match[1]; - _format = _format.replace(match[1] + mapper.key, ''); - } - - var endStr = i === map.length - 1 ? _format : ''; - - if (mapper.apply) { - return str + mapper.apply.call(null, date) + endStr; - } - - return str + endStr; + return formatters.reduce(function(str, formatter) { + return str + formatter(date); }, ''); }; @@ -1330,6 +1438,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst maxMode: 'year', minDate: null, minMode: 'day', + monthColumns: 3, ngModelOptions: {}, shortcutPropagation: false, showWeeks: true, @@ -1337,13 +1446,15 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst yearRows: 4 }) -.controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser', - function($scope, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) { +.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser', + function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) { var self = this, ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl; ngModelOptions = {}, - watchListeners = [], - optionsUsed = !!$attrs.datepickerOptions; + watchListeners = []; + + $element.addClass('uib-datepicker'); + $attrs.$set('role', 'application'); if (!$scope.datepickerOptions) { $scope.datepickerOptions = {}; @@ -1366,6 +1477,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst 'maxMode', 'minDate', 'minMode', + 'monthColumns', 'showWeeks', 'shortcutPropagation', 'startingDay', @@ -1391,6 +1503,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $interpolate($scope.datepickerOptions[key])($scope.$parent) : datepickerConfig[key]; break; + case 'monthColumns': case 'showWeeks': case 'shortcutPropagation': case 'yearColumns': @@ -1435,7 +1548,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst case 'minMode': if ($scope.datepickerOptions[key]) { $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) { - self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key]; + self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key]; if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) || key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) { $scope.datepickerMode = self[key]; @@ -1470,7 +1583,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst this.init = function(ngModelCtrl_) { ngModelCtrl = ngModelCtrl_; - ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions; + ngModelOptions = ngModelCtrl_.$options || + $scope.datepickerOptions.ngModelOptions || + datepickerConfig.ngModelOptions; if ($scope.datepickerOptions.initDate) { self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date(); $scope.$watch('datepickerOptions.initDate', function(initDate) { @@ -1642,6 +1757,12 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst } }; + $element.on('keydown', function(evt) { + $scope.$apply(function() { + $scope.keydown(evt); + }); + }); + $scope.$on('$destroy', function() { //Clear all watch listeners on destroy while (watchListeners.length) { @@ -1792,7 +1913,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst } scope.title = dateFilter(this.activeDate, this.formatMonthTitle); - scope.rows = this.split(months, 3); + scope.rows = this.split(months, this.monthColumns); + scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1; }; this.compare = function(date1, date2) { @@ -1809,11 +1931,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst if (key === 'left') { date = date - 1; } else if (key === 'up') { - date = date - 3; + date = date - this.monthColumns; } else if (key === 'right') { date = date + 1; } else if (key === 'down') { - date = date + 3; + date = date + this.monthColumns; } else if (key === 'pageup' || key === 'pagedown') { var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); this.activeDate.setFullYear(year); @@ -1884,7 +2006,6 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .directive('uibDatepicker', function() { return { - replace: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/datepicker/datepicker.html'; }, @@ -1892,6 +2013,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst datepickerOptions: '=?' }, require: ['uibDatepicker', '^ngModel'], + restrict: 'A', controller: 'UibDatepickerController', controllerAs: 'datepicker', link: function(scope, element, attrs, ctrls) { @@ -1904,11 +2026,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .directive('uibDaypicker', function() { return { - replace: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/datepicker/day.html'; }, require: ['^uibDatepicker', 'uibDaypicker'], + restrict: 'A', controller: 'UibDaypickerController', link: function(scope, element, attrs, ctrls) { var datepickerCtrl = ctrls[0], @@ -1921,11 +2043,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .directive('uibMonthpicker', function() { return { - replace: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/datepicker/month.html'; }, require: ['^uibDatepicker', 'uibMonthpicker'], + restrict: 'A', controller: 'UibMonthpickerController', link: function(scope, element, attrs, ctrls) { var datepickerCtrl = ctrls[0], @@ -1938,11 +2060,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst .directive('uibYearpicker', function() { return { - replace: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/datepicker/year.html'; }, require: ['^uibDatepicker', 'uibYearpicker'], + restrict: 'A', controller: 'UibYearpickerController', link: function(scope, element, attrs, ctrls) { var ctrl = ctrls[0]; @@ -2086,7 +2208,7 @@ angular.module('ui.bootstrap.position', []) var paddingRight = this.parseStyle(elemStyle.paddingRight); var paddingBottom = this.parseStyle(elemStyle.paddingBottom); var scrollParent = this.scrollParent(elem, false, true); - var scrollbarWidth = this.scrollbarWidth(scrollParent, BODY_REGEX.test(scrollParent.tagName)); + var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName)); return { scrollbarWidth: scrollbarWidth, @@ -2485,13 +2607,33 @@ angular.module('ui.bootstrap.position', []) }, /** - * Provides a way for positioning tooltip & dropdown - * arrows when using placement options beyond the standard - * left, right, top, or bottom. - * - * @param {element} elem - The tooltip/dropdown element. - * @param {string} placement - The placement for the elem. - */ + * Provides a way to adjust the top positioning after first + * render to correctly align element to top after content + * rendering causes resized element height + * + * @param {array} placementClasses - The array of strings of classes + * element should have. + * @param {object} containerPosition - The object with container + * position information + * @param {number} initialHeight - The initial height for the elem. + * @param {number} currentHeight - The current height for the elem. + */ + adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) { + if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) { + return { + top: containerPosition.top - currentHeight + 'px' + }; + } + }, + + /** + * Provides a way for positioning tooltip & dropdown + * arrows when using placement options beyond the standard + * left, right, top, or bottom. + * + * @param {element} elem - The tooltip/dropdown element. + * @param {string} placement - The placement for the elem. + */ positionArrow: function(elem, placement) { elem = this.getRawNode(elem); @@ -2585,12 +2727,15 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ isHtml5DateInput = false; var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus, datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl, - ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [], - timezone; + ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = []; this.init = function(_ngModel_) { ngModel = _ngModel_; - ngModelOptions = _ngModel_.$options; + ngModelOptions = angular.isObject(_ngModel_.$options) ? + _ngModel_.$options : + { + timezone: null + }; closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ? $scope.$parent.$eval($attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection; @@ -2642,19 +2787,6 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ // popup element used to display calendar popupEl = angular.element('
'); - if (ngModelOptions) { - timezone = ngModelOptions.timezone; - $scope.ngModelOptions = angular.copy(ngModelOptions); - $scope.ngModelOptions.timezone = null; - if ($scope.ngModelOptions.updateOnDefault === true) { - $scope.ngModelOptions.updateOn = $scope.ngModelOptions.updateOn ? - $scope.ngModelOptions.updateOn + ' default' : 'default'; - } - - popupEl.attr('ng-model-options', 'ngModelOptions'); - } else { - timezone = null; - } popupEl.attr({ 'ng-model': 'date', @@ -2694,13 +2826,13 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ value = new Date(value); } - $scope.date = dateParser.fromTimezone(value, timezone); + $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone); return dateParser.filter($scope.date, dateFormat); }); } else { ngModel.$formatters.push(function(value) { - $scope.date = dateParser.fromTimezone(value, timezone); + $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone); return value; }); } @@ -2752,7 +2884,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ $scope.isDisabled = function(date) { if (date === 'today') { - date = dateParser.fromTimezone(new Date(), timezone); + date = dateParser.fromTimezone(new Date(), ngModelOptions.timezone); } var dates = {}; @@ -2760,7 +2892,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ if (!$scope.datepickerOptions[key]) { dates[key] = null; } else if (angular.isDate($scope.datepickerOptions[key])) { - dates[key] = dateParser.fromTimezone(new Date($scope.datepickerOptions[key]), timezone); + dates[key] = new Date($scope.datepickerOptions[key]); } else { if ($datepickerPopupLiteralWarning) { $log.warn('Literal date support has been deprecated, please switch to date object usage'); @@ -2781,9 +2913,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ // Inner change $scope.dateSelection = function(dt) { - if (angular.isDefined(dt)) { - $scope.date = dt; - } + $scope.date = dt; var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function $element.val(date); ngModel.$setViewValue(date); @@ -2811,7 +2941,8 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ date = new Date($scope.date); date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); } else { - date = new Date(today.setHours(0, 0, 0, 0)); + date = dateParser.fromTimezone(today, ngModelOptions.timezone); + date.setHours(0, 0, 0, 0); } } $scope.dateSelection(date); @@ -2901,7 +3032,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ if (angular.isString(viewValue)) { var date = parseDateString(viewValue); if (!isNaN(date)) { - return dateParser.toTimezone(date, timezone); + return dateParser.fromTimezone(date, ngModelOptions.timezone); } } @@ -2928,7 +3059,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ } if (angular.isString(value)) { - return !isNaN(parseDateString(viewValue)); + return !isNaN(parseDateString(value)); } return false; @@ -3007,7 +3138,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ .directive('uibDatepickerPopupWrap', function() { return { - replace: true, + restrict: 'A', transclude: true, templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html'; @@ -3050,7 +3181,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) this.open = function(dropdownScope, element) { if (!openScope) { $document.on('click', closeDropdown); - element.on('keydown', keybindFilter); } if (openScope && openScope !== dropdownScope) { @@ -3062,9 +3192,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) this.close = function(dropdownScope, element) { if (openScope === dropdownScope) { - openScope = null; $document.off('click', closeDropdown); - element.off('keydown', keybindFilter); + $document.off('keydown', this.keybindFilter); + openScope = null; } }; @@ -3088,6 +3218,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) return; } + openScope.focusToggleElement(); openScope.isOpen = false; if (!$rootScope.$$phase) { @@ -3095,12 +3226,21 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } }; - var keybindFilter = function(evt) { + this.keybindFilter = function(evt) { + if (!openScope) { + // see this.close as ESC could have been pressed which kills the scope so we can not proceed + return; + } + + var dropdownElement = openScope.getDropdownElement(); + var toggleElement = openScope.getToggleElement(); + var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target); + var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target); if (evt.which === 27) { evt.stopPropagation(); openScope.focusToggleElement(); closeDropdown(); - } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen) { + } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) { evt.preventDefault(); evt.stopPropagation(); openScope.focusDropdownEntry(evt.which); @@ -3231,7 +3371,8 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true), css, rightalign, - scrollbarWidth; + scrollbarPadding, + scrollbarWidth = 0; css = { top: pos.top + 'px', @@ -3244,7 +3385,12 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) css.right = 'auto'; } else { css.left = 'auto'; - scrollbarWidth = $position.scrollbarWidth(true); + scrollbarPadding = $position.scrollbarPadding(appendTo); + + if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) { + scrollbarWidth = scrollbarPadding.scrollbarWidth; + } + css.right = window.innerWidth - scrollbarWidth - (pos.left + $element.prop('offsetWidth')) + 'px'; } @@ -3286,13 +3432,17 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) var newEl = dropdownElement; self.dropdownMenu.replaceWith(newEl); self.dropdownMenu = newEl; + $document.on('keydown', uibDropdownService.keybindFilter); }); }); + } else { + $document.on('keydown', uibDropdownService.keybindFilter); } scope.focusToggleElement(); uibDropdownService.open(scope, $element); } else { + uibDropdownService.close(scope, $element); if (self.dropdownMenuTemplateUrl) { if (templateScope) { templateScope.$destroy(); @@ -3302,7 +3452,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) self.dropdownMenu = newEl; } - uibDropdownService.close(scope, $element); self.selectedOption = null; } @@ -3426,7 +3575,7 @@ angular.module('ui.bootstrap.stackedMap', []) return stack.splice(idx, 1)[0]; }, removeTop: function() { - return stack.splice(stack.length - 1, 1)[0]; + return stack.pop(); }, length: function() { return stack.length; @@ -3543,8 +3692,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack', function($animate, $injector, $modalStack) { return { - replace: true, - templateUrl: 'uib/template/modal/backdrop.html', + restrict: 'A', compile: function(tElement, tAttrs) { tElement.addClass(tAttrs.backdropClass); return linkFn; @@ -3573,13 +3721,12 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p scope: { index: '@' }, - replace: true, + restrict: 'A', transclude: true, templateUrl: function(tElement, tAttrs) { return tAttrs.templateUrl || 'uib/template/modal/window.html'; }, link: function(scope, element, attrs) { - element.addClass(attrs.windowClass || ''); element.addClass(attrs.windowTopClass || ''); scope.size = attrs.size; @@ -3602,14 +3749,11 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}. scope.$isRendered = true; - // Deferred object that will be resolved when this modal is render. + // Deferred object that will be resolved when this modal is rendered. var modalRenderDeferObj = $q.defer(); - // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready. - // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template. - attrs.$observe('modalRender', function(value) { - if (value === 'true') { - modalRenderDeferObj.resolve(); - } + // Resolve render promise post-digest + scope.$$postDigest(function() { + modalRenderDeferObj.resolve(); }); modalRenderDeferObj.promise.then(function() { @@ -3638,7 +3782,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p /** * If something within the freshly-opened modal already has focus (perhaps via a - * directive that causes focus). then no need to try and focus anything. + * directive that causes focus) then there's no need to try to focus anything. */ if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) { var inputWithAutofocus = element[0].querySelector('[autofocus]'); @@ -3672,16 +3816,16 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p }; }) - .directive('uibModalTransclude', function() { + .directive('uibModalTransclude', ['$animate', function($animate) { return { link: function(scope, element, attrs, controller, transclude) { transclude(scope.$parent, function(clone) { element.empty(); - element.append(clone); + $animate.enter(clone, element); }); } }; - }) + }]) .factory('$uibModalStack', ['$animate', '$animateCss', '$document', '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition', @@ -3696,12 +3840,22 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p }; var topModalIndex = 0; var previousTopOpenedModal = null; + var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count'; //Modal focus behavior - var tabableSelector = 'a[href], area[href], input:not([disabled]), ' + - 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' + - 'iframe, object, embed, *[tabindex], *[contenteditable=true]'; + var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' + + 'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' + + 'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]'; var scrollbarPadding; + var SNAKE_CASE_REGEXP = /[A-Z]/g; + + // TODO: extract into common dependency with tooltip + function snake_case(name) { + var separator = '-'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } function isVisible(element) { return !!(element.offsetWidth || @@ -3817,6 +3971,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p afterAnimating.done = true; $animate.leave(domEl).then(function() { + if (done) { + done(); + } + domEl.remove(); if (closedDeferred) { closedDeferred.resolve(); @@ -3824,9 +3982,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p }); scope.$destroy(); - if (done) { - done(); - } } } @@ -3914,57 +4069,147 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p backdropScope.modalOptions = modal; backdropScope.index = currBackdropIndex; backdropDomEl = angular.element('
'); - backdropDomEl.attr('backdrop-class', modal.backdropClass); + backdropDomEl.attr({ + 'class': 'modal-backdrop', + 'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}', + 'uib-modal-animation-class': 'fade', + 'modal-in-class': 'in' + }); + if (modal.backdropClass) { + backdropDomEl.addClass(modal.backdropClass); + } + if (modal.animation) { backdropDomEl.attr('modal-animation', 'true'); } $compile(backdropDomEl)(backdropScope); $animate.enter(backdropDomEl, appendToElement); - scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement); - if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) { - appendToElement.css({paddingRight: scrollbarPadding.right + 'px'}); + if ($uibPosition.isScrollable(appendToElement)) { + scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement); + if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) { + appendToElement.css({paddingRight: scrollbarPadding.right + 'px'}); + } } } + var content; + if (modal.component) { + content = document.createElement(snake_case(modal.component.name)); + content = angular.element(content); + content.attr({ + resolve: '$resolve', + 'modal-instance': '$uibModalInstance', + close: '$close($value)', + dismiss: '$dismiss($value)' + }); + } else { + content = modal.content; + } + // Set the top modal index based on the index of the previous top modal topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0; var angularDomEl = angular.element('
'); angularDomEl.attr({ + 'class': 'modal', 'template-url': modal.windowTemplateUrl, - 'window-class': modal.windowClass, 'window-top-class': modal.windowTopClass, + 'role': 'dialog', + 'aria-labelledby': modal.ariaLabelledBy, + 'aria-describedby': modal.ariaDescribedBy, 'size': modal.size, 'index': topModalIndex, - 'animate': 'animate' - }).html(modal.content); + 'animate': 'animate', + 'ng-style': '{\'z-index\': 1050 + $$topModalIndex*10, display: \'block\'}', + 'tabindex': -1, + 'uib-modal-animation-class': 'fade', + 'modal-in-class': 'in' + }).append(content); + if (modal.windowClass) { + angularDomEl.addClass(modal.windowClass); + } + if (modal.animation) { angularDomEl.attr('modal-animation', 'true'); } appendToElement.addClass(modalBodyClass); + if (modal.scope) { + // we need to explicitly add the modal index to the modal scope + // because it is needed by ngStyle to compute the zIndex property. + modal.scope.$$topModalIndex = topModalIndex; + } $animate.enter($compile(angularDomEl)(modal.scope), appendToElement); openedWindows.top().value.modalDomEl = angularDomEl; openedWindows.top().value.modalOpener = modalOpener; + + applyAriaHidden(angularDomEl); + + function applyAriaHidden(el) { + if (!el || el[0].tagName === 'BODY') { + return; + } + + getSiblings(el).forEach(function(sibling) { + var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true', + ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10); + + if (!ariaHiddenCount) { + ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0; + } + + sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1); + sibling.setAttribute('aria-hidden', 'true'); + }); + + return applyAriaHidden(el.parent()); + + function getSiblings(el) { + var children = el.parent() ? el.parent().children() : []; + + return Array.prototype.filter.call(children, function(child) { + return child !== el[0]; + }); + } + } }; function broadcastClosing(modalWindow, resultOrReason, closing) { return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented; } + function unhideBackgroundElements() { + Array.prototype.forEach.call( + document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'), + function(hiddenEl) { + var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10), + newHiddenCount = ariaHiddenCount - 1; + hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount); + + if (!newHiddenCount) { + hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME); + hiddenEl.removeAttribute('aria-hidden'); + } + } + ); + } + $modalStack.close = function(modalInstance, result) { var modalWindow = openedWindows.get(modalInstance); + unhideBackgroundElements(); if (modalWindow && broadcastClosing(modalWindow, result, true)) { modalWindow.value.modalScope.$$uibDestructionScheduled = true; modalWindow.value.deferred.resolve(result); removeModalWindow(modalInstance, modalWindow.value.modalOpener); return true; } + return !modalWindow; }; $modalStack.dismiss = function(modalInstance, reason) { var modalWindow = openedWindows.get(modalInstance); + unhideBackgroundElements(); if (modalWindow && broadcastClosing(modalWindow, reason, false)) { modalWindow.value.modalScope.$$uibDestructionScheduled = true; modalWindow.value.deferred.reject(reason); @@ -3987,6 +4232,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p $modalStack.modalRendered = function(modalInstance) { var modalWindow = openedWindows.get(modalInstance); + $modalStack.focusFirstFocusableElement($modalStack.loadFocusElementList(modalWindow)); if (modalWindow) { modalWindow.value.renderDeferred.resolve(); } @@ -4036,7 +4282,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p if (modalWindow) { var modalDomE1 = modalWindow.value.modalDomEl; if (modalDomE1 && modalDomE1.length) { - var elements = modalDomE1[0].querySelectorAll(tabableSelector); + var elements = modalDomE1[0].querySelectorAll(tabbableSelector); return elements ? Array.prototype.filter.call(elements, function(element) { return isVisible(element); @@ -4096,12 +4342,17 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0); //verify options - if (!modalOptions.template && !modalOptions.templateUrl) { - throw new Error('One of template or templateUrl options is required.'); + if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of component or template or templateUrl options is required.'); } - var templateAndResolvePromise = - $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]); + var templateAndResolvePromise; + if (modalOptions.component) { + templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null)); + } else { + templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]); + } function resolveWithTemplate() { return templateAndResolvePromise; @@ -4127,17 +4378,34 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p } }); + var modal = { + scope: modalScope, + deferred: modalResultDeferred, + renderDeferred: modalRenderDeferred, + closedDeferred: modalClosedDeferred, + animation: modalOptions.animation, + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowTopClass: modalOptions.windowTopClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + ariaLabelledBy: modalOptions.ariaLabelledBy, + ariaDescribedBy: modalOptions.ariaDescribedBy, + size: modalOptions.size, + openedClass: modalOptions.openedClass, + appendTo: modalOptions.appendTo + }; + + var component = {}; var ctrlInstance, ctrlInstantiate, ctrlLocals = {}; - //controllers - if (modalOptions.controller) { - ctrlLocals.$scope = modalScope; - ctrlLocals.$scope.$resolve = {}; - ctrlLocals.$uibModalInstance = modalInstance; - angular.forEach(tplAndVars[1], function(value, key) { - ctrlLocals[key] = value; - ctrlLocals.$scope.$resolve[key] = value; - }); + if (modalOptions.component) { + constructLocals(component, false, true, false); + component.name = modalOptions.component; + modal.component = component; + } else if (modalOptions.controller) { + constructLocals(ctrlLocals, true, false, true); // the third param will make the controller instantiate later,private api // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126 @@ -4158,25 +4426,31 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p } } - $modalStack.open(modalInstance, { - scope: modalScope, - deferred: modalResultDeferred, - renderDeferred: modalRenderDeferred, - closedDeferred: modalClosedDeferred, - content: tplAndVars[0], - animation: modalOptions.animation, - backdrop: modalOptions.backdrop, - keyboard: modalOptions.keyboard, - backdropClass: modalOptions.backdropClass, - windowTopClass: modalOptions.windowTopClass, - windowClass: modalOptions.windowClass, - windowTemplateUrl: modalOptions.windowTemplateUrl, - size: modalOptions.size, - openedClass: modalOptions.openedClass, - appendTo: modalOptions.appendTo - }); + if (!modalOptions.component) { + modal.content = tplAndVars[0]; + } + + $modalStack.open(modalInstance, modal); modalOpenedDeferred.resolve(true); + function constructLocals(obj, template, instanceOnScope, injectable) { + obj.$scope = modalScope; + obj.$scope.$resolve = {}; + if (instanceOnScope) { + obj.$scope.$uibModalInstance = modalInstance; + } else { + obj.$uibModalInstance = modalInstance; + } + + var resolves = template ? tplAndVars[1] : tplAndVars; + angular.forEach(resolves, function(value, key) { + if (injectable) { + obj[key] = value; + } + + obj.$scope.$resolve[key] = value; + }); + } }, function resolveError(reason) { modalOpenedDeferred.reject(reason); modalResultDeferred.reject(reason); @@ -4290,7 +4564,7 @@ angular.module('ui.bootstrap.paging', []) }; }]); -angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging']) +angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex']) .controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) { $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align; @@ -4314,13 +4588,14 @@ angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging']) ngDisabled: '=' }, require: ['uibPager', '?ngModel'], + restrict: 'A', controller: 'UibPagerController', controllerAs: 'pager', templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/pager/pager.html'; }, - replace: true, link: function(scope, element, attrs, ctrls) { + element.addClass('pager'); var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; if (!ngModelCtrl) { @@ -4332,7 +4607,7 @@ angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging']) }; }]); -angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging']) +angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex']) .controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) { var ctrl = this; // Setup configuration parameters @@ -4466,13 +4741,14 @@ angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging']) ngDisabled:'=' }, require: ['uibPagination', '?ngModel'], + restrict: 'A', controller: 'UibPaginationController', controllerAs: 'pagination', templateUrl: function(element, attrs) { return attrs.templateUrl || 'uib/template/pagination/pagination.html'; }, - replace: true, link: function(scope, element, attrs, ctrls) { + element.addClass('pagination'); var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; if (!ngModelCtrl) { @@ -4557,10 +4833,10 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s */ this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) { var openedTooltips = $$stackedMap.createNew(); - $document.on('keypress', keypressListener); + $document.on('keyup', keypressListener); $rootScope.$on('$destroy', function() { - $document.off('keypress', keypressListener); + $document.off('keyup', keypressListener); }); function keypressListener(e) { @@ -4568,7 +4844,6 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s var last = openedTooltips.top(); if (last) { last.value.close(); - openedTooltips.removeTop(); last = null; } } @@ -4612,12 +4887,11 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s (options.useContentExp ? 'content-exp="contentExp()" ' : 'content="' + startSym + 'content' + endSym + '" ') + - 'placement="' + startSym + 'placement' + endSym + '" ' + - 'popup-class="' + startSym + 'popupClass' + endSym + '" ' + - 'animation="animation" ' + - 'is-open="isOpen" ' + 'origin-scope="origScope" ' + - 'class="uib-position-measure"' + + 'class="uib-position-measure ' + prefix + '" ' + + 'tooltip-animation-class="fade"' + + 'uib-tooltip-classes ' + + 'ng-class="{ in: isOpen }" ' + '>' + ''; @@ -4632,6 +4906,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s var showTimeout; var hideTimeout; var positionTimeout; + var adjustmentTimeout; var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; var triggers = getTriggers(undefined); var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']); @@ -4649,11 +4924,14 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s if (!positionTimeout) { positionTimeout = $timeout(function() { var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight'); + var elementPos = appendToBody ? $position.offset(element) : $position.position(element); tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' }); + var placementClasses = ttPosition.placement.split('-'); - if (!tooltip.hasClass(ttPosition.placement.split('-')[0])) { + if (!tooltip.hasClass(placementClasses[0])) { tooltip.removeClass(lastPlacement.split('-')[0]); - tooltip.addClass(ttPosition.placement.split('-')[0]); + tooltip.addClass(placementClasses[0]); } if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) { @@ -4661,6 +4939,15 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s tooltip.addClass(options.placementClassPrefix + ttPosition.placement); } + adjustmentTimeout = $timeout(function() { + var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight'); + var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight); + if (adjustment) { + tooltip.css(adjustment); + } + adjustmentTimeout = null; + }, 0, false); + // first time through tt element will have the // uib-position-measure class or if the placement // has changed we need to position the arrow. @@ -4683,9 +4970,6 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s // By default, the tooltip is not open. // TODO add ability to start tooltip opened ttScope.isOpen = false; - openedTooltips.add(ttScope, { - close: hide - }); function toggleTooltipBind() { if (!ttScope.isOpen) { @@ -4812,6 +5096,10 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s } }); + openedTooltips.add(ttScope, { + close: hide + }); + prepObservers(); } @@ -4822,8 +5110,15 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s if (tooltip) { tooltip.remove(); + tooltip = null; + if (adjustmentTimeout) { + $timeout.cancel(adjustmentTimeout); + } } + + openedTooltips.remove(ttScope); + if (tooltipLinkedScope) { tooltipLinkedScope.$destroy(); tooltipLinkedScope = null; @@ -4982,10 +5277,22 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s }; function prepTriggers() { - var val = attrs[prefix + 'Trigger']; + var showTriggers = [], hideTriggers = []; + var val = scope.$eval(attrs[prefix + 'Trigger']); unregisterTriggers(); - triggers = getTriggers(val); + if (angular.isObject(val)) { + Object.keys(val).forEach(function(key) { + showTriggers.push(key); + hideTriggers.push(val[key]); + }); + triggers = { + show: showTriggers, + hide: hideTriggers + }; + } else { + triggers = getTriggers(val); + } if (triggers.show !== 'none') { triggers.show.forEach(function(trigger, idx) { @@ -5027,7 +5334,6 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s scope.$on('$destroy', function onDestroyTooltip() { unregisterTriggers(); removeTooltip(); - openedTooltips.remove(ttScope); ttScope = null; }); }; @@ -5130,7 +5436,7 @@ function ($animate, $sce, $compile, $templateRequest) { element.addClass(scope.popupClass); } - if (scope.animation()) { + if (scope.animation) { element.addClass(attrs.tooltipAnimationClass); } } @@ -5139,8 +5445,8 @@ function ($animate, $sce, $compile, $templateRequest) { .directive('uibTooltipPopup', function() { return { - replace: true, - scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + restrict: 'A', + scope: { content: '@' }, templateUrl: 'uib/template/tooltip/tooltip-popup.html' }; }) @@ -5151,9 +5457,8 @@ function ($animate, $sce, $compile, $templateRequest) { .directive('uibTooltipTemplatePopup', function() { return { - replace: true, - scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', - originScope: '&' }, + restrict: 'A', + scope: { contentExp: '&', originScope: '&' }, templateUrl: 'uib/template/tooltip/tooltip-template-popup.html' }; }) @@ -5166,8 +5471,8 @@ function ($animate, $sce, $compile, $templateRequest) { .directive('uibTooltipHtmlPopup', function() { return { - replace: true, - scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + restrict: 'A', + scope: { contentExp: '&' }, templateUrl: 'uib/template/tooltip/tooltip-html-popup.html' }; }) @@ -5187,9 +5492,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip']) .directive('uibPopoverTemplatePopup', function() { return { - replace: true, - scope: { uibTitle: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&', - originScope: '&' }, + restrict: 'A', + scope: { uibTitle: '@', contentExp: '&', originScope: '&' }, templateUrl: 'uib/template/popover/popover-template.html' }; }) @@ -5202,8 +5506,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip']) .directive('uibPopoverHtmlPopup', function() { return { - replace: true, - scope: { contentExp: '&', uibTitle: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + restrict: 'A', + scope: { contentExp: '&', uibTitle: '@' }, templateUrl: 'uib/template/popover/popover-html.html' }; }) @@ -5216,8 +5520,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip']) .directive('uibPopoverPopup', function() { return { - replace: true, - scope: { uibTitle: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' }, + restrict: 'A', + scope: { uibTitle: '@', content: '@' }, templateUrl: 'uib/template/popover/popover.html' }; }) @@ -5344,7 +5648,7 @@ angular.module('ui.bootstrap.rating', []) stateOn: null, stateOff: null, enableReset: true, - titles : ['one', 'two', 'three', 'four', 'five'] + titles: ['one', 'two', 'three', 'four', 'five'] }) .controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) { @@ -5429,6 +5733,7 @@ angular.module('ui.bootstrap.rating', []) .directive('uibRating', function() { return { require: ['uibRating', 'ngModel'], + restrict: 'A', scope: { readonly: '=?readOnly', onHover: '&', @@ -5436,7 +5741,6 @@ angular.module('ui.bootstrap.rating', []) }, controller: 'UibRatingController', templateUrl: 'uib/template/rating/rating.html', - replace: true, link: function(scope, element, attrs, ctrls) { var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; ratingCtrl.init(ngModelCtrl); @@ -5698,6 +6002,7 @@ angular.module('ui.bootstrap.timepicker', []) }) .controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) { + var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl; var selected = new Date(), watchers = [], ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl @@ -5719,6 +6024,10 @@ angular.module('ui.bootstrap.timepicker', []) minutesInputEl = inputs.eq(1), secondsInputEl = inputs.eq(2); + hoursModelCtrl = hoursInputEl.controller('ngModel'); + minutesModelCtrl = minutesInputEl.controller('ngModel'); + secondsModelCtrl = secondsInputEl.controller('ngModel'); + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; if (mousewheel) { @@ -5978,14 +6287,23 @@ angular.module('ui.bootstrap.timepicker', []) ngModelCtrl.$setValidity('time', false); if (angular.isDefined(invalidHours)) { $scope.invalidHours = invalidHours; + if (hoursModelCtrl) { + hoursModelCtrl.$setValidity('hours', false); + } } if (angular.isDefined(invalidMinutes)) { $scope.invalidMinutes = invalidMinutes; + if (minutesModelCtrl) { + minutesModelCtrl.$setValidity('minutes', false); + } } if (angular.isDefined(invalidSeconds)) { $scope.invalidSeconds = invalidSeconds; + if (secondsModelCtrl) { + secondsModelCtrl.$setValidity('seconds', false); + } } }; @@ -6108,6 +6426,18 @@ angular.module('ui.bootstrap.timepicker', []) } function makeValid() { + if (hoursModelCtrl) { + hoursModelCtrl.$setValidity('hours', true); + } + + if (minutesModelCtrl) { + minutesModelCtrl.$setValidity('minutes', true); + } + + if (secondsModelCtrl) { + secondsModelCtrl.$setValidity('seconds', true); + } + ngModelCtrl.$setValidity('time', true); $scope.invalidHours = false; $scope.invalidMinutes = false; @@ -6230,9 +6560,9 @@ angular.module('ui.bootstrap.timepicker', []) .directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) { return { require: ['uibTimepicker', '?^ngModel'], + restrict: 'A', controller: 'UibTimepickerController', controllerAs: 'timepicker', - replace: true, scope: {}, templateUrl: function(element, attrs) { return attrs.templateUrl || uibTimepickerConfig.templateUrl; @@ -6254,7 +6584,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap * Extracted to a separate service for ease of unit testing */ .factory('uibTypeaheadParser', ['$parse', function($parse) { - // 00000111000000000000022200000000000000003333333333333330000000000044000 + // 000001111111100000000000002222222200000000000000003333333333333330000000000044444444000 var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; return { parse: function(input) { @@ -6401,6 +6731,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap 'vertical-align': 'top', 'background-color': 'transparent' }); + + if (hintInputElem.attr('id')) { + hintInputElem.removeAttr('id'); // remove duplicate id if present. + } inputsContainer.append(hintInputElem); hintInputElem.after(element); } @@ -6651,13 +6985,13 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap case 38: // up arrow scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; scope.$digest(); - target = popUpEl.find('li')[scope.activeIdx]; + target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx]; target.parentNode.scrollTop = target.offsetTop; break; case 40: // down arrow scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; scope.$digest(); - target = popUpEl.find('li')[scope.activeIdx]; + target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx]; target.parentNode.scrollTop = target.offsetTop; break; default: @@ -6699,9 +7033,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap } if (!isEditable && modelCtrl.$error.editable) { modelCtrl.$setViewValue(); - // Reset validity as we are clearing - modelCtrl.$setValidity('editable', true); - modelCtrl.$setValidity('parse', true); + scope.$apply(function() { + // Reset validity as we are clearing + modelCtrl.$setValidity('editable', true); + modelCtrl.$setValidity('parse', true); + }); element.val(''); } hasFocus = false; @@ -6919,15 +7255,13 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap angular.module("uib/template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/accordion/accordion-group.html", - "
\n" + - "
\n" + - "

\n" + - " {{heading}}\n" + - "

\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + + "
\n" + + "

\n" + + " {{heading}}\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + ""); }]); @@ -6939,63 +7273,57 @@ angular.module("uib/template/accordion/accordion.html", []).run(["$templateCache angular.module("uib/template/alert/alert.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/alert/alert.html", - "
\n" + - " \n" + - "
\n" + - "
\n" + + "\n" + + "
\n" + ""); }]); angular.module("uib/template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/carousel/carousel.html", - "
\n" + - "
\n" + - " 1\">\n" + - " \n" + - " previous\n" + - " \n" + - " 1\">\n" + - " \n" + - " next\n" + - " \n" + - "
    1\">\n" + - "
  1. \n" + - " slide {{ $index + 1 }} of {{ slides.length }}, currently active\n" + - "
  2. \n" + - "
\n" + - "
\n" + + "
\n" + + " 1\">\n" + + " \n" + + " previous\n" + + "\n" + + " 1\">\n" + + " \n" + + " next\n" + + "\n" + + "
    1\">\n" + + "
  1. \n" + + " slide {{ $index + 1 }} of {{ slides.length }}, currently active\n" + + "
  2. \n" + + "
\n" + ""); }]); angular.module("uib/template/carousel/slide.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/carousel/slide.html", - "
\n" + + "
\n" + ""); }]); angular.module("uib/template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/datepicker/datepicker.html", - "
\n" + - " \n" + - " \n" + - " \n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + "
\n" + ""); }]); angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/datepicker/day.html", - "\n" + + "
\n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -7003,7 +7331,7 @@ angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", fu " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + "
{{ weekNumbers[$index] }}\n" + + "\n" + " \n" + " \n" + - " \n" + - " \n" + - " \n" + + " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + - " \n" + + " \n" + "
\n" + @@ -7055,16 +7383,16 @@ angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/datepicker/year.html", - "\n" + + "
\n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + " \n" + - " \n" + + " \n" + "
\n" + @@ -7085,147 +7413,96 @@ angular.module("uib/template/datepicker/year.html", []).run(["$templateCache", f angular.module("uib/template/datepickerPopup/popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/datepickerPopup/popup.html", - "
\n" + - "
    \n" + - "
  • \n" + - "
  • \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
  • \n" + - "
\n" + - "
\n" + - ""); -}]); - -angular.module("uib/template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("uib/template/modal/backdrop.html", - "
\n" + + "
    \n" + + "
  • \n" + + "
  • \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
  • \n" + + "
\n" + ""); }]); angular.module("uib/template/modal/window.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/modal/window.html", - "
\n" + - "
\n" + - "
\n" + + "
\n" + ""); }]); angular.module("uib/template/pager/pager.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/pager/pager.html", - "\n" + + "
  • {{::getText('previous')}}
  • \n" + + "
  • {{::getText('next')}}
  • \n" + ""); }]); angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/pagination/pagination.html", - "\n" + + "
  • {{::getText('first')}}
  • \n" + + "
  • {{::getText('previous')}}
  • \n" + + "
  • {{page.text}}
  • \n" + + "
  • {{::getText('next')}}
  • \n" + + "
  • {{::getText('last')}}
  • \n" + ""); }]); angular.module("uib/template/tooltip/tooltip-html-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/tooltip/tooltip-html-popup.html", - "
    \n" + - "
    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "
    \n" + ""); }]); angular.module("uib/template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/tooltip/tooltip-popup.html", - "
    \n" + - "
    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "
    \n" + ""); }]); angular.module("uib/template/tooltip/tooltip-template-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/tooltip/tooltip-template-popup.html", - "
    \n" + - "
    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "
    \n" + ""); }]); angular.module("uib/template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/popover/popover-html.html", - "
    \n" + - "
    \n" + + "
    \n" + "\n" + - "
    \n" + - "

    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "

    \n" + + "
    \n" + "
    \n" + ""); }]); angular.module("uib/template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/popover/popover-template.html", - "
    \n" + - "
    \n" + + "
    \n" + "\n" + - "
    \n" + - "

    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "

    \n" + + "
    \n" + "
    \n" + ""); }]); angular.module("uib/template/popover/popover.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/popover/popover.html", - "
    \n" + - "
    \n" + + "
    \n" + "\n" + - "
    \n" + - "

    \n" + - "
    \n" + - "
    \n" + + "
    \n" + + "

    \n" + + "
    \n" + "
    \n" + ""); }]); @@ -7286,11 +7563,11 @@ angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCac "\n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -7308,11 +7585,11 @@ angular.module("uib/template/timepicker/timepicker.html", []).run(["$templateCac " \n" + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + - " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -7332,7 +7609,7 @@ angular.module("uib/template/typeahead/typeahead-match.html", []).run(["$templat angular.module("uib/template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/typeahead/typeahead-popup.html", "
      \n" + - "
    • \n" + + "
    • \n" + "
      \n" + "
    • \n" + "
    \n" + -- cgit v1.2.1