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

Datepicker refactor #1120

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions src/datepicker/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
maxDate: null
})

.service('DatepickerService', ['datepickerConfig', function(datepickerConfig) {
var WATCHABLE_KEYS = ['showWeeks', 'minDate', 'maxDate'];

function styleHyphenFormat(propertyName) {
function upperToHyphenLower(match) {
return '-' + match.toLowerCase();
}
return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}

this.collectConfigAttributes = function(attrs, callback) {
var currentKey;
for (currentKey in attrs) {
if (datepickerConfig.hasOwnProperty(currentKey)) {
callback(attrs[currentKey], currentKey, styleHyphenFormat(currentKey), WATCHABLE_KEYS.indexOf(currentKey) !== -1);
}
}
};
}])

.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
var format = {
day: getValue($attrs.dayFormat, dtConfig.dayFormat),
Expand Down Expand Up @@ -134,7 +154,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
require: ['datepicker', '?^ngModel'],
controller: 'DatepickerController',
link: function(scope, element, attrs, ctrls) {
var datepickerCtrl = ctrls[0], ngModel = ctrls[1];
var datepickerCtrl = ctrls[0], ngModel = ctrls[1],
minDate = attrs.min || attrs.minDate, maxDate = attrs.max || attrs.maxDate;

if (!ngModel) {
return; // do nothing if no ng-model
Expand All @@ -152,14 +173,14 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
updateShowWeekNumbers();
}

if (attrs.min) {
scope.$parent.$watch($parse(attrs.min), function(value) {
if (minDate) {
scope.$parent.$watch($parse(minDate), function(value) {
datepickerCtrl.minDate = value ? new Date(value) : null;
refill();
});
}
if (attrs.max) {
scope.$parent.$watch($parse(attrs.max), function(value) {
if (maxDate) {
scope.$parent.$watch($parse(maxDate), function(value) {
datepickerCtrl.maxDate = value ? new Date(value) : null;
refill();
});
Expand Down Expand Up @@ -260,8 +281,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position'])
closeOnDateSelection: true
})

.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig',
function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig) {
.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'DatepickerService',
function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, DatepickerService) {
return {
restrict: 'EA',
require: 'ngModel',
Expand Down Expand Up @@ -397,14 +418,23 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon
datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty);
}
}
addWatchableAttribute(attrs.min, 'min');
addWatchableAttribute(attrs.max, 'max');
if (attrs.showWeeks) {
addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks');
} else {
scope.showWeeks = true;
datepickerEl.attr('show-weeks', 'showWeeks');

DatepickerService.collectConfigAttributes(attrs, function(attribute, scopeProperty, datepickerAttribute, watchable) {
if (watchable) {
addWatchableAttribute(attribute, scopeProperty, datepickerAttribute);
} else {
datepickerEl.attr(datepickerAttribute, attribute);
}
});

if (!datepickerEl.attr('min-date') && attrs.min) {
addWatchableAttribute(attrs.min, 'min');
}

if (!datepickerEl.attr('max-date') && attrs.max) {
addWatchableAttribute(attrs.max, 'max');
}

if (attrs.dateDisabled) {
datepickerEl.attr('date-disabled', attrs.dateDisabled);
}
Expand Down
198 changes: 198 additions & 0 deletions src/datepicker/test/datepicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,204 @@ describe('datepicker directive', function () {
expect(inputEl.val()).toBe('pizza');
});
});

describe('with `show-weeks` attribute', function() {
beforeEach(inject(function () {
$rootScope.showWeeks = false;
var wrapElement = $compile('<div><input ng-model="date" datepicker-popup show-weeks="showWeeks"><div>')($rootScope);
$rootScope.$digest();
assignElements(wrapElement);
}));

it('to hide weeks column', function() {
expect(getWeeks()).toEqual(['', '', '', '', '']);
});
it('to show weeks column', function() {
$rootScope.showWeeks = true;
$rootScope.$digest();
expect(getWeeks()).toEqual(["34", "35", "36", "37", "38"]);
});
});

describe('with `min` attribute', function() {
beforeEach(function () {
$rootScope.mindate = new Date("September 12, 2010");
element = $compile('<div><input ng-model="date" datepicker-popup min="mindate"><div>')($rootScope);
$rootScope.$digest();
});

it('disables appropriate days in current month', function () {
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 7; j++) {
expect(isDisabledOption(i, j)).toBe((i < 2));
}
}
});

it('disables appropriate days when min date changes', function() {
$rootScope.mindate = new Date("September 5, 2010");
$rootScope.$digest();
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i < 1) );
}
}
});
});

describe('with `minDate` attribute', function() {
beforeEach(function () {
$rootScope.mindate = new Date("September 12, 2010");
element = $compile('<div><input ng-model="date" datepicker-popup min-date="mindate"><div>')($rootScope);
$rootScope.$digest();
});

it('disables appropriate days in current month', function () {
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 7; j++) {
expect(isDisabledOption(i, j)).toBe((i < 2));
}
}
});

it('disables appropriate days when min date changes', function() {
$rootScope.mindate = new Date("September 5, 2010");
$rootScope.$digest();
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i < 1) );
}
}
});
});

describe('with `max` attribute', function() {
beforeEach(function() {
$rootScope.maxdate = new Date("September 25, 2010");
element = $compile('<div><input ng-model="date" datepicker-popup max="maxdate"><div>')($rootScope);
$rootScope.$digest();
});

it('disables appropriate days in current month', function() {
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i === 4) );
}
}
});

it('disables appropriate days when max date changes', function() {
$rootScope.maxdate = new Date("September 18, 2010");
$rootScope.$digest();
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i > 2) );
}
}
});
});

describe('with `maxDate` attribute', function() {
beforeEach(function() {
$rootScope.maxdate = new Date("September 25, 2010");
element = $compile('<div><input ng-model="date" datepicker-popup max-date="maxdate"><div>')($rootScope);
$rootScope.$digest();
});

it('disables appropriate days in current month', function() {
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i === 4) );
}
}
});

it('disables appropriate days when max date changes', function() {
$rootScope.maxdate = new Date("September 18, 2010");
$rootScope.$digest();
for (var i = 0; i < 5; i ++) {
for (var j = 0; j < 7; j ++) {
expect(isDisabledOption(i, j)).toBe( (i > 2) );
}
}
});
});

describe('with `day-title-format` attribute', function() {
beforeEach(function() {
$rootScope.maxdate = new Date("September 25, 2010");
element = $compile('<div><input ng-model="date" datepicker-popup day-title-format="\'MMMM, yy\'"><div>')($rootScope);
$rootScope.$digest();
});

it('changes the title format in `day` mode', function() {
expect(getTitle()).toBe('September, 10');
});
});

describe('with datepickerOptions', function() {
beforeEach(inject(function() {
$rootScope.datepickerOptions = {
'starting-day': 6,
'show-weeks': false,
'day-format': "'d'",
'month-format': "'MMM'",
'year-format': "'yy'",
'year-range': 10,
'day-header-format': "'EEEE'",
'day-title-format': "'MMMM, yy'",
'month-title-format': "'yy'"
};

element = $compile('<div><input ng-model="date" datepicker-popup datepicker-options="datepickerOptions"><div>')($rootScope);
$rootScope.$digest();
}));

it('changes the title format in `day` mode', function() {
expect(getTitle()).toBe('September, 10');
});

it('changes the title & months format in `month` mode', function() {
clickTitleButton();

expect(getTitle()).toBe('10');
expect(getOptions()).toEqual([
['Jan', 'Feb', 'Mar'],
['Apr', 'May', 'Jun'],
['Jul', 'Aug', 'Sep'],
['Oct', 'Nov', 'Dec']
]);
});

it('changes the title, year format & range in `year` mode', function() {
clickTitleButton(2);

expect(getTitle()).toBe('01 - 10');
expect(getOptions()).toEqual([
['01', '02', '03', '04', '05'],
['06', '07', '08', '09', '10']
]);
});

it('changes the `starting-day` & day headers & format', function() {
expect(getLabels()).toEqual(['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']);
expect(getOptions()).toEqual([
['28', '29', '30', '31', '1', '2', '3'],
['4', '5', '6', '7', '8', '9', '10'],
['11', '12', '13', '14', '15', '16', '17'],
['18', '19', '20', '21', '22', '23', '24'],
['25', '26', '27', '28', '29', '30', '1']
]);
});

it('changes initial visibility for weeks', function() {
expect(getLabelsRow().find('th').eq(0).css('display')).toBe('none');
var tr = element.find('tbody').find('tr');
for (var i = 0; i < 5; i++) {
expect(tr.eq(i).find('td').eq(0).css('display')).toBe('none');
}
});
});
});
});

Expand Down