From fa90c1da36e004132824ac5aab58f468245ff0d1 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 21 Jan 2020 10:11:35 +0100 Subject: Upgrade to version 2.5.0 Change-Id: I9111a768fac27bccb7c17027a8b4a667ce9011f9 --- setup.cfg | 6 +- xstatic/pkg/angular_bootstrap/__init__.py | 6 +- .../angular_bootstrap/data/angular-bootstrap.js | 508 +++++++++++++-------- 3 files changed, 336 insertions(+), 184 deletions(-) diff --git a/setup.cfg b/setup.cfg index 0f43a6e..a70f214 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,9 @@ [metadata] name = XStatic-Angular-Bootstrap -description = Angular-Bootstrap 2.2.0 (XStatic packaging standard) +description = Angular-Bootstrap 2.5.0 (XStatic packaging standard) description-file = README.rst -maintainer = Rob Cresswell -maintainer-email = robert.cresswell@outlook.com +maintainer = Radomir Dopieralski +maintainer-email = openstack@sheep.art.pl home-page = http://angular-ui.github.io/bootstrap/ keywords = angular_bootstrap xstatic license = MIT diff --git a/xstatic/pkg/angular_bootstrap/__init__.py b/xstatic/pkg/angular_bootstrap/__init__.py index ed1afdd..352b509 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 = '2.2.0' # version of the packaged files, please use the upstream +VERSION = '2.5.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. @@ -24,8 +24,8 @@ CLASSIFIERS = [] KEYWORDS = '%s xstatic' % NAME # XStatic-* package maintainer: -MAINTAINER = 'Rob Cresswell' -MAINTAINER_EMAIL = 'robert.cresswell@outlook.com' +MAINTAINER = 'Radomir Dopieralski' +MAINTAINER_EMAIL = 'openstack@sheep.art.pl' # this refers to the project homepage of the stuff we packaged: HOMEPAGE = 'http://angular-ui.github.io/bootstrap/' diff --git a/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js b/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js index 2ee890e..6783893 100644 --- a/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js +++ b/xstatic/pkg/angular_bootstrap/data/angular-bootstrap.js @@ -2,9 +2,9 @@ * angular-ui-bootstrap * http://angular-ui.github.io/bootstrap/ - * Version: 2.2.0 - 2016-10-10 + * Version: 2.5.0 - 2017-01-28 * License: MIT - */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", ["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.multiMap","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', []) @@ -80,7 +80,7 @@ angular.module('ui.bootstrap.collapse', []) to: getScrollFromElement(element[0]) }).then(expandDone); } - }); + }, angular.noop); } function expandDone() { @@ -119,7 +119,7 @@ angular.module('ui.bootstrap.collapse', []) to: cssTo }).then(collapseDone); } - }); + }, angular.noop); } function collapseDone() { @@ -436,7 +436,7 @@ angular.module('ui.bootstrap.carousel', []) slides = self.slides = $scope.slides = [], SLIDE_DIRECTION = 'uib-slideDirection', currentIndex = $scope.active, - currentInterval, isPlaying, bufferedTransitions = []; + currentInterval, isPlaying; var destroyed = false; $element.addClass('carousel'); @@ -498,11 +498,6 @@ angular.module('ui.bootstrap.carousel', []) self.removeSlide = function(slide) { var index = findSlideIndex(slide); - var bufferedIndex = bufferedTransitions.indexOf(slides[index]); - if (bufferedIndex !== -1) { - bufferedTransitions.splice(bufferedIndex, 1); - } - //get the index of the slide inside the carousel slides.splice(index, 1); if (slides.length > 0 && currentIndex === index) { @@ -526,7 +521,6 @@ angular.module('ui.bootstrap.carousel', []) if (slides.length === 0) { currentIndex = null; $scope.active = null; - clearBufferedTransitions(); } }; @@ -541,8 +535,6 @@ angular.module('ui.bootstrap.carousel', []) if (nextSlide.slide.index !== currentIndex && !$scope.$currentTransition) { goNext(nextSlide.slide, nextIndex, direction); - } else if (nextSlide && nextSlide.slide.index !== currentIndex && $scope.$currentTransition) { - bufferedTransitions.push(slides[nextIndex]); } }; @@ -611,12 +603,6 @@ angular.module('ui.bootstrap.carousel', []) } }); - function clearBufferedTransitions() { - while (bufferedTransitions.length) { - bufferedTransitions.shift(); - } - } - function getSlideByIndex(index) { for (var i = 0, l = slides.length; i < l; ++i) { if (slides[i].index === index) { @@ -652,14 +638,6 @@ angular.module('ui.bootstrap.carousel', []) if (phase === 'close') { $scope.$currentTransition = null; $animate.off('addClass', element); - if (bufferedTransitions.length) { - var nextSlide = bufferedTransitions.pop().slide; - var nextIndex = nextSlide.index; - var nextDirection = nextIndex > self.getCurrentIndex() ? 'next' : 'prev'; - clearBufferedTransitions(); - - goNext(nextSlide, nextIndex, nextDirection); - } } }); } @@ -690,7 +668,6 @@ angular.module('ui.bootstrap.carousel', []) function resetTransition(slides) { if (!slides.length) { $scope.$currentTransition = null; - clearBufferedTransitions(); } } @@ -811,7 +788,7 @@ function($animateCss) { angular.module('ui.bootstrap.dateparser', []) -.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', function($log, $locale, dateFilter, orderByFilter) { +.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', 'filterFilter', function($log, $locale, dateFilter, orderByFilter, filterFilter) { // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; @@ -1041,10 +1018,36 @@ angular.module('ui.bootstrap.dateparser', []) formatter: function(date) { return dateFilter(date, 'G'); } } ]; + + if (angular.version.major >= 1 && angular.version.minor > 4) { + formatCodeToRegex.push({ + key: 'LLLL', + regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); }, + formatter: function(date) { return dateFilter(date, 'LLLL'); } + }); + } }; this.init(); + function getFormatCodeToRegex(key) { + return filterFilter(formatCodeToRegex, {key: key}, true)[0]; + } + + this.getParser = function (key) { + var f = getFormatCodeToRegex(key); + return f && f.apply || null; + }; + + this.overrideParser = function (key, parser) { + var f = getFormatCodeToRegex(key); + if (f && angular.isFunction(parser)) { + this.parsers = {}; + f.apply = parser; + } + }.bind(this); + function createParser(format) { var map = [], regex = format.split(''); @@ -1526,7 +1529,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $scope.$watch('datepickerOptions.' + key, function(value) { if (value) { if (angular.isDate(value)) { - self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone); + self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone')); } else { if ($datepickerLiteralWarning) { $log.warn('Literal date support has been deprecated, please switch to date object usage'); @@ -1536,7 +1539,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst } } else { self[key] = datepickerConfig[key] ? - dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : + dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) : null; } @@ -1583,14 +1586,13 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst this.init = function(ngModelCtrl_) { ngModelCtrl = ngModelCtrl_; - ngModelOptions = ngModelCtrl_.$options || - $scope.datepickerOptions.ngModelOptions || - datepickerConfig.ngModelOptions; + ngModelOptions = extractOptions(ngModelCtrl); + if ($scope.datepickerOptions.initDate) { - self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date(); + self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date(); $scope.$watch('datepickerOptions.initDate', function(initDate) { if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { - self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone); + self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone')); self.refreshView(); } }); @@ -1600,8 +1602,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date(); this.activeDate = !isNaN(date) ? - dateParser.fromTimezone(date, ngModelOptions.timezone) : - dateParser.fromTimezone(new Date(), ngModelOptions.timezone); + dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) : + dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone')); ngModelCtrl.$render = function() { self.render(); @@ -1614,7 +1616,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst isValid = !isNaN(date); if (isValid) { - this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone); + this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')); } else if (!$datepickerSuppressError) { $log.error('Datepicker directive: "ng-model" value must be a Date object'); } @@ -1631,7 +1633,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst } var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - date = dateParser.fromTimezone(date, ngModelOptions.timezone); + date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')); ngModelCtrl.$setValidity('dateDisabled', !date || this.element && !this.isDisabled(date)); } @@ -1639,9 +1641,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst this.createDateObject = function(date, format) { var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - model = dateParser.fromTimezone(model, ngModelOptions.timezone); + model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone')); var today = new Date(); - today = dateParser.fromTimezone(today, ngModelOptions.timezone); + today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone')); var time = this.compare(date, today); var dt = { date: date, @@ -1687,9 +1689,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $scope.select = function(date) { if ($scope.datepickerMode === self.minMode) { - var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0); + var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0); dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - dt = dateParser.toTimezone(dt, ngModelOptions.timezone); + dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone')); ngModelCtrl.$setViewValue(dt); ngModelCtrl.$render(); } else { @@ -1774,6 +1776,37 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $scope.datepickerMode = mode; $scope.datepickerOptions.datepickerMode = mode; } + + function extractOptions(ngModelCtrl) { + var ngModelOptions; + + if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing + // guarantee a value + ngModelOptions = ngModelCtrl.$options || + $scope.datepickerOptions.ngModelOptions || + datepickerConfig.ngModelOptions || + {}; + + // mimic 1.6+ api + ngModelOptions.getOption = function (key) { + return ngModelOptions[key]; + }; + } else { // in angular >=1.6 $options is always present + // ng-model-options defaults timezone to null; don't let its precedence squash a non-null value + var timezone = ngModelCtrl.$options.getOption('timezone') || + ($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) || + (datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null); + + // values passed to createChild override existing values + ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance + .createChild(datepickerConfig.ngModelOptions) // lowest precedence + .createChild($scope.datepickerOptions.ngModelOptions) + .createChild(ngModelCtrl.$options) // highest precedence + .createChild({timezone: timezone}); // to keep from squashing a non-null value + } + + return ngModelOptions; + } }]) .controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { @@ -2731,11 +2764,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ this.init = function(_ngModel_) { ngModel = _ngModel_; - ngModelOptions = angular.isObject(_ngModel_.$options) ? - _ngModel_.$options : - { - timezone: null - }; + ngModelOptions = extractOptions(ngModel); closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ? $scope.$parent.$eval($attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection; @@ -2826,13 +2855,13 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ value = new Date(value); } - $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone); + $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone')); return dateParser.filter($scope.date, dateFormat); }); } else { ngModel.$formatters.push(function(value) { - $scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone); + $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone')); return value; }); } @@ -2884,7 +2913,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ $scope.isDisabled = function(date) { if (date === 'today') { - date = dateParser.fromTimezone(new Date(), ngModelOptions.timezone); + date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone')); } var dates = {}; @@ -2941,7 +2970,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ date = new Date($scope.date); date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); } else { - date = dateParser.fromTimezone(today, ngModelOptions.timezone); + date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone')); date.setHours(0, 0, 0, 0); } } @@ -3032,11 +3061,11 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ if (angular.isString(viewValue)) { var date = parseDateString(viewValue); if (!isNaN(date)) { - return dateParser.fromTimezone(date, ngModelOptions.timezone); + return dateParser.toTimezone(date, ngModelOptions.getOption('timezone')); } } - return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined; + return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined; } function validator(modelValue, viewValue) { @@ -3111,6 +3140,28 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $ } } + function extractOptions(ngModelCtrl) { + var ngModelOptions; + + if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing + // guarantee a value + ngModelOptions = angular.isObject(ngModelCtrl.$options) ? + ngModelCtrl.$options : + { + timezone: null + }; + + // mimic 1.6+ api + ngModelOptions.getOption = function (key) { + return ngModelOptions[key]; + }; + } else { // in angular >=1.6 $options is always present + ngModelOptions = ngModelCtrl.$options; + } + + return ngModelOptions; + } + $scope.$on('uib:datepicker.mode', function() { $timeout(positionPopup, 0, false); }); @@ -3168,17 +3219,92 @@ angular.module('ui.bootstrap.debounce', []) }; }]); -angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) +angular.module('ui.bootstrap.multiMap', []) +/** + * A helper, internal data structure that stores all references attached to key + */ + .factory('$$multiMap', function() { + return { + createNew: function() { + var map = {}; + + return { + entries: function() { + return Object.keys(map).map(function(key) { + return { + key: key, + value: map[key] + }; + }); + }, + get: function(key) { + return map[key]; + }, + hasKey: function(key) { + return !!map[key]; + }, + keys: function() { + return Object.keys(map); + }, + put: function(key, value) { + if (!map[key]) { + map[key] = []; + } + + map[key].push(value); + }, + remove: function(key, value) { + var values = map[key]; + + if (!values) { + return; + } + + var idx = values.indexOf(value); + + if (idx !== -1) { + values.splice(idx, 1); + } + + if (!values.length) { + delete map[key]; + } + } + }; + } + }; + }); + +angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.multiMap', 'ui.bootstrap.position']) .constant('uibDropdownConfig', { appendToOpenClass: 'uib-dropdown-open', openClass: 'open' }) -.service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) { +.service('uibDropdownService', ['$document', '$rootScope', '$$multiMap', function($document, $rootScope, $$multiMap) { var openScope = null; + var openedContainers = $$multiMap.createNew(); + + this.isOnlyOpen = function(dropdownScope, appendTo) { + var openedDropdowns = openedContainers.get(appendTo); + if (openedDropdowns) { + var openDropdown = openedDropdowns.reduce(function(toClose, dropdown) { + if (dropdown.scope === dropdownScope) { + return dropdown; + } - this.open = function(dropdownScope, element) { + return toClose; + }, {}); + if (openDropdown) { + return openedDropdowns.length === 1; + } + } + + return false; + }; + + this.open = function(dropdownScope, element, appendTo) { if (!openScope) { $document.on('click', closeDropdown); } @@ -3188,20 +3314,58 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } openScope = dropdownScope; + + if (!appendTo) { + return; + } + + var openedDropdowns = openedContainers.get(appendTo); + if (openedDropdowns) { + var openedScopes = openedDropdowns.map(function(dropdown) { + return dropdown.scope; + }); + if (openedScopes.indexOf(dropdownScope) === -1) { + openedContainers.put(appendTo, { + scope: dropdownScope + }); + } + } else { + openedContainers.put(appendTo, { + scope: dropdownScope + }); + } }; - this.close = function(dropdownScope, element) { + this.close = function(dropdownScope, element, appendTo) { if (openScope === dropdownScope) { $document.off('click', closeDropdown); $document.off('keydown', this.keybindFilter); openScope = null; } + + if (!appendTo) { + return; + } + + var openedDropdowns = openedContainers.get(appendTo); + if (openedDropdowns) { + var dropdownToClose = openedDropdowns.reduce(function(toClose, dropdown) { + if (dropdown.scope === dropdownScope) { + return dropdown; + } + + return toClose; + }, {}); + if (dropdownToClose) { + openedContainers.remove(appendTo, dropdownToClose); + } + } }; var closeDropdown = function(evt) { // This method may still be called during the same mouse event that // unbound this event handler. So check openScope before proceeding. - if (!openScope) { return; } + if (!openScope || !openScope.isOpen) { return; } if (evt && openScope.getAutoClose() === 'disabled') { return; } @@ -3257,8 +3421,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, - appendToBody = false, - appendTo = null, keynavEnabled = false, selectedOption = null, body = $document.find('body'); @@ -3275,26 +3437,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) }); } - if (angular.isDefined($attrs.dropdownAppendTo)) { - var appendToEl = $parse($attrs.dropdownAppendTo)(scope); - if (appendToEl) { - appendTo = angular.element(appendToEl); - } - } - - appendToBody = angular.isDefined($attrs.dropdownAppendToBody); keynavEnabled = angular.isDefined($attrs.keyboardNav); - - if (appendToBody && !appendTo) { - appendTo = body; - } - - if (appendTo && self.dropdownMenu) { - appendTo.append(self.dropdownMenu); - $element.on('$destroy', function handleDestroyEvent() { - self.dropdownMenu.remove(); - }); - } }; this.toggle = function(open) { @@ -3366,7 +3509,42 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } }; + function removeDropdownMenu() { + $element.append(self.dropdownMenu); + } + scope.$watch('isOpen', function(isOpen, wasOpen) { + var appendTo = null, + appendToBody = false; + + if (angular.isDefined($attrs.dropdownAppendTo)) { + var appendToEl = $parse($attrs.dropdownAppendTo)(scope); + if (appendToEl) { + appendTo = angular.element(appendToEl); + } + } + + if (angular.isDefined($attrs.dropdownAppendToBody)) { + var appendToBodyValue = $parse($attrs.dropdownAppendToBody)(scope); + if (appendToBodyValue !== false) { + appendToBody = true; + } + } + + if (appendToBody && !appendTo) { + appendTo = body; + } + + if (appendTo && self.dropdownMenu) { + if (isOpen) { + appendTo.append(self.dropdownMenu); + $element.on('$destroy', removeDropdownMenu); + } else { + $element.off('$destroy', removeDropdownMenu); + removeDropdownMenu(); + } + } + if (appendTo && self.dropdownMenu) { var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true), css, @@ -3414,10 +3592,18 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } var openContainer = appendTo ? appendTo : $element; - var hasOpenClass = openContainer.hasClass(appendTo ? appendToOpenClass : openClass); + var dropdownOpenClass = appendTo ? appendToOpenClass : openClass; + var hasOpenClass = openContainer.hasClass(dropdownOpenClass); + var isOnlyOpen = uibDropdownService.isOnlyOpen($scope, appendTo); if (hasOpenClass === !isOpen) { - $animate[isOpen ? 'addClass' : 'removeClass'](openContainer, appendTo ? appendToOpenClass : openClass).then(function() { + var toggleClass; + if (appendTo) { + toggleClass = !isOnlyOpen ? 'addClass' : 'removeClass'; + } else { + toggleClass = isOpen ? 'addClass' : 'removeClass'; + } + $animate[toggleClass](openContainer, dropdownOpenClass).then(function() { if (angular.isDefined(isOpen) && isOpen !== wasOpen) { toggleInvoker($scope, { open: !!isOpen }); } @@ -3440,9 +3626,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } scope.focusToggleElement(); - uibDropdownService.open(scope, $element); + uibDropdownService.open(scope, $element, appendTo); } else { - uibDropdownService.close(scope, $element); + uibDropdownService.close(scope, $element, appendTo); if (self.dropdownMenuTemplateUrl) { if (templateScope) { templateScope.$destroy(); @@ -3515,7 +3701,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) } }; - element.bind('click', toggleDropdown); + element.on('click', toggleDropdown); // WAI-ARIA element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); @@ -3524,7 +3710,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) }); scope.$on('$destroy', function() { - element.unbind('click', toggleDropdown); + element.off('click', toggleDropdown); }); } }; @@ -3584,62 +3770,7 @@ angular.module('ui.bootstrap.stackedMap', []) } }; }); -angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.position']) -/** - * A helper, internal data structure that stores all references attached to key - */ - .factory('$$multiMap', function() { - return { - createNew: function() { - var map = {}; - - return { - entries: function() { - return Object.keys(map).map(function(key) { - return { - key: key, - value: map[key] - }; - }); - }, - get: function(key) { - return map[key]; - }, - hasKey: function(key) { - return !!map[key]; - }, - keys: function() { - return Object.keys(map); - }, - put: function(key, value) { - if (!map[key]) { - map[key] = []; - } - - map[key].push(value); - }, - remove: function(key, value) { - var values = map[key]; - - if (!values) { - return; - } - - var idx = values.indexOf(value); - - if (idx !== -1) { - values.splice(idx, 1); - } - - if (!values.length) { - delete map[key]; - } - } - }; - } - }; - }) - +angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.stackedMap', 'ui.bootstrap.position']) /** * Pluggable resolve mechanism for the modal resolve resolution * Supports UI Router's $resolve service @@ -4060,10 +4191,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p var appendToElement = modal.appendTo, currBackdropIndex = backdropIndex(); - if (!appendToElement.length) { - throw new Error('appendTo element not found. Make sure that the element passed is in DOM.'); - } - if (currBackdropIndex >= 0 && !backdropDomEl) { backdropScope = $rootScope.$new(true); backdropScope.modalOptions = modal; @@ -4155,7 +4282,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10); if (!ariaHiddenCount) { - ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0; + ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0; } sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1); @@ -4193,7 +4320,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p } ); } - + $modalStack.close = function(modalInstance, result) { var modalWindow = openedWindows.get(modalInstance); unhideBackgroundElements(); @@ -4232,7 +4359,6 @@ 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(); } @@ -4341,6 +4467,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p modalOptions.resolve = modalOptions.resolve || {}; modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0); + if (!modalOptions.appendTo.length) { + throw new Error('appendTo element not found. Make sure that the element passed is in DOM.'); + } + //verify options if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) { throw new Error('One of component or template or templateUrl options is required.'); @@ -4618,6 +4748,7 @@ angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap. pageLabel = angular.isDefined($attrs.pageLabel) ? function(idx) { return $scope.$parent.$eval($attrs.pageLabel, {$page: idx}); } : angular.identity; $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks; $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks; + $attrs.$set('role', 'menu'); uibPaging.create(this, $scope, $attrs); @@ -5258,6 +5389,13 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s } } + // KeyboardEvent handler to hide the tooltip on Escape key press + function hideOnEscapeKey(e) { + if (e.which === 27) { + hideTooltipBind(); + } + } + var unregisterTriggers = function() { triggers.show.forEach(function(trigger) { if (trigger === 'outsideClick') { @@ -5266,6 +5404,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s element.off(trigger, showTooltipBind); element.off(trigger, toggleTooltipBind); } + element.off('keypress', hideOnEscapeKey); }); triggers.hide.forEach(function(trigger) { if (trigger === 'outsideClick') { @@ -5305,12 +5444,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s element.on(trigger, showTooltipBind); element.on(triggers.hide[idx], hideTooltipBind); } - - element.on('keypress', function(e) { - if (e.which === 27) { - hideTooltipBind(); - } - }); + element.on('keypress', hideOnEscapeKey); }); } } @@ -6207,21 +6341,21 @@ angular.module('ui.bootstrap.timepicker', []) return e.detail || delta > 0; }; - hoursInputEl.bind('mousewheel wheel', function(e) { + hoursInputEl.on('mousewheel wheel', function(e) { if (!disabled) { $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours()); } e.preventDefault(); }); - minutesInputEl.bind('mousewheel wheel', function(e) { + minutesInputEl.on('mousewheel wheel', function(e) { if (!disabled) { $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes()); } e.preventDefault(); }); - secondsInputEl.bind('mousewheel wheel', function(e) { + secondsInputEl.on('mousewheel wheel', function(e) { if (!disabled) { $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds()); } @@ -6231,7 +6365,7 @@ angular.module('ui.bootstrap.timepicker', []) // Respond on up/down arrowkeys this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) { - hoursInputEl.bind('keydown', function(e) { + hoursInputEl.on('keydown', function(e) { if (!disabled) { if (e.which === 38) { // up e.preventDefault(); @@ -6245,7 +6379,7 @@ angular.module('ui.bootstrap.timepicker', []) } }); - minutesInputEl.bind('keydown', function(e) { + minutesInputEl.on('keydown', function(e) { if (!disabled) { if (e.which === 38) { // up e.preventDefault(); @@ -6259,7 +6393,7 @@ angular.module('ui.bootstrap.timepicker', []) } }); - secondsInputEl.bind('keydown', function(e) { + secondsInputEl.on('keydown', function(e) { if (!disabled) { if (e.which === 38) { // up e.preventDefault(); @@ -6326,7 +6460,7 @@ angular.module('ui.bootstrap.timepicker', []) } }; - hoursInputEl.bind('blur', function(e) { + hoursInputEl.on('blur', function(e) { ngModelCtrl.$setTouched(); if (modelIsEmpty()) { makeValid(); @@ -6358,7 +6492,7 @@ angular.module('ui.bootstrap.timepicker', []) } }; - minutesInputEl.bind('blur', function(e) { + minutesInputEl.on('blur', function(e) { ngModelCtrl.$setTouched(); if (modelIsEmpty()) { makeValid(); @@ -6384,7 +6518,7 @@ angular.module('ui.bootstrap.timepicker', []) } }; - secondsInputEl.bind('blur', function(e) { + secondsInputEl.on('blur', function(e) { if (modelIsEmpty()) { makeValid(); } else if (!$scope.invalidSeconds && $scope.seconds < 10) { @@ -6673,7 +6807,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap var invokeModelSetter = $parse(attrs.ngModel + '($$$p)'); var $setModelValue = function(scope, newValue) { if (angular.isFunction(parsedModel(originalScope)) && - ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { + ngModelOptions.getOption('getterSetter')) { return invokeModelSetter(scope, {$$$p: newValue}); } @@ -7009,7 +7143,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap } }); - element.bind('focus', function (evt) { + element.on('focus', function (evt) { hasFocus = true; if (minLength === 0 && !modelCtrl.$viewValue) { $timeout(function() { @@ -7018,7 +7152,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap } }); - element.bind('blur', function(evt) { + element.on('blur', function(evt) { if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { selected = true; scope.$apply(function() { @@ -7086,11 +7220,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap element.after($popup); } - this.init = function(_modelCtrl, _ngModelOptions) { + this.init = function(_modelCtrl) { modelCtrl = _modelCtrl; - ngModelOptions = _ngModelOptions; + ngModelOptions = extractOptions(modelCtrl); - scope.debounceUpdate = modelCtrl.$options && $parse(modelCtrl.$options.debounce)(originalScope); + scope.debounceUpdate = $parse(ngModelOptions.getOption('debounce'))(originalScope); //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue @@ -7150,14 +7284,32 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; }); }; + + function extractOptions(ngModelCtrl) { + var ngModelOptions; + + if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing + // guarantee a value + ngModelOptions = ngModelCtrl.$options || {}; + + // mimic 1.6+ api + ngModelOptions.getOption = function (key) { + return ngModelOptions[key]; + }; + } else { // in angular >=1.6 $options is always present + ngModelOptions = ngModelCtrl.$options; + } + + return ngModelOptions; + } }]) .directive('uibTypeahead', function() { return { controller: 'UibTypeaheadController', - require: ['ngModel', '^?ngModelOptions', 'uibTypeahead'], + require: ['ngModel', 'uibTypeahead'], link: function(originalScope, element, attrs, ctrls) { - ctrls[2].init(ctrls[0], ctrls[1]); + ctrls[1].init(ctrls[0]); } }; }) @@ -7441,11 +7593,11 @@ angular.module("uib/template/pager/pager.html", []).run(["$templateCache", funct angular.module("uib/template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("uib/template/pagination/pagination.html", - "
  • {{::getText('first')}}
  • \n" + - "
  • {{::getText('previous')}}
  • \n" + - "
  • {{page.text}}
  • \n" + - "
  • {{::getText('next')}}
  • \n" + - "
  • {{::getText('last')}}
  • \n" + + "
  • {{::getText('first')}}
  • \n" + + "
  • {{::getText('previous')}}
  • \n" + + "
  • {{page.text}}
  • \n" + + "
  • {{::getText('next')}}
  • \n" + + "
  • {{::getText('last')}}
  • \n" + ""); }]); -- cgit v1.2.1