Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Update to Angular 1.6 #6427

Closed
wants to merge 13 commits into from
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
"url": "https://github.com/angular-ui/bootstrap.git"
},
"devDependencies": {
"angular": "1.5.8",
"angular-mocks": "1.5.8",
"angular-sanitize": "1.5.8",
"angular": "1.6.1",
"angular-mocks": "1.6.1",
"angular-sanitize": "1.6.1",
"grunt": "^0.4.5",
"grunt-cli": "^1.2.0",
"grunt-contrib-concat": "^1.0.0",
Expand Down
4 changes: 2 additions & 2 deletions src/accordion/test/accordion.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ describe('uib-accordion', function() {
});

it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).find('span.ng-scope').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
});

it('should wrap the transcluded content in a span', function() {
Expand Down Expand Up @@ -580,7 +580,7 @@ describe('uib-accordion', function() {
});

it('attaches the same scope to the transcluded heading and body', function() {
expect(findGroupLink(0).find('span.ng-scope').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
});

it('should have disabled styling when is-disabled is true', isDisabledStyleCheck);
Expand Down
2 changes: 1 addition & 1 deletion src/alert/test/alert.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('uib-alert', function() {
}

function findContent(index) {
return element.find('div[ng-transclude] span').eq(index);
return element.find('div[ng-transclude]').eq(index);
}

it('should expose the controller to the view', function() {
Expand Down
4 changes: 2 additions & 2 deletions src/collapse/collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ angular.module('ui.bootstrap.collapse', [])
to: getScrollFromElement(element[0])
}).then(expandDone);
}
});
}, angular.noop);
}

function expandDone() {
Expand Down Expand Up @@ -111,7 +111,7 @@ angular.module('ui.bootstrap.collapse', [])
to: cssTo
}).then(collapseDone);
}
});
}, angular.noop);
}

function collapseDone() {
Expand Down
60 changes: 45 additions & 15 deletions src/datepicker/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,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');
Expand All @@ -114,7 +114,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;
}

Expand Down Expand Up @@ -161,14 +161,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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto with getOption

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

$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();
}
});
Expand All @@ -178,8 +177,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();
Expand All @@ -192,7 +191,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');
}
Expand All @@ -209,17 +208,17 @@ 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));
}
};

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,
Expand Down Expand Up @@ -265,9 +264,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 {
Expand Down Expand Up @@ -352,6 +351,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) {
Expand Down
40 changes: 29 additions & 11 deletions src/datepickerPopup/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,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;
Expand Down Expand Up @@ -127,13 +123,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;
});
}
Expand Down Expand Up @@ -185,7 +181,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 = {};
Expand Down Expand Up @@ -242,7 +238,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);
}
}
Expand Down Expand Up @@ -333,11 +329,11 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
if (angular.isString(viewValue)) {
var date = parseDateString(viewValue);
if (!isNaN(date)) {
return dateParser.toTimezone(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) {
Expand Down Expand Up @@ -412,6 +408,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);
});
Expand Down
8 changes: 4 additions & 4 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.sta
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;
Expand Down Expand Up @@ -699,6 +695,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.sta
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.');
Expand Down
11 changes: 8 additions & 3 deletions src/modal/test/modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ describe('$uibModal', function() {

function open(modalOptions, noFlush, noDigest) {
var modal = $uibModal.open(modalOptions);
modal.opened['catch'](angular.noop);
modal.result['catch'](angular.noop);

if (!noDigest) {
$rootScope.$digest();
Expand Down Expand Up @@ -1612,7 +1614,7 @@ describe('$uibModal', function() {
var windowEl = $compile('<div uib-modal-window template-url="window.html">content</div>')($rootScope);
$rootScope.$digest();

expect(windowEl.html()).toBe('<div ng-transclude=""><span class="ng-scope">content</span></div>');
expect(windowEl.html()).toBe('<div ng-transclude="">content</div>');
}));
});

Expand Down Expand Up @@ -1736,16 +1738,19 @@ describe('$uibModal', function() {
ds[x] = {index: i, deferred: $q.defer(), reject: reject};

var scope = $rootScope.$new();
var failed = false;
scope.index = i;
open({
template: '<div>' + i + '</div>',
scope: scope,
resolve: {
x: function() { return ds[x].deferred.promise; }
x: function() { return ds[x].deferred.promise['catch'](function () {
failed = true;
}); }
}
}, true).opened.then(function() {
expect($uibModalStack.getTop().value.modalScope.index).toEqual(i);
actual += i;
if (!failed) { actual += i; }
});
});

Expand Down
30 changes: 24 additions & 6 deletions src/typeahead/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,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});
}

Expand Down Expand Up @@ -507,11 +507,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
Expand Down Expand Up @@ -571,14 +571,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]);
}
};
})
Expand Down