Skip to content

Commit 7f0f5ca

Browse files
author
Brad Berger
committed
Fixes issues #15, #17, #19
1 parent 162d048 commit 7f0f5ca

11 files changed

+549
-46
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
- Fixes bug with incorrect use of one-time bindings, resulting in the
44
dates not updating.
55

6+
- Fixes bug with empty weeks being added, messing up the row heights.
7+
68
## 0.2.7
79

810
- Adds selection of multiple dates

dist/angular-material-calendar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<md-content layout='column' layout-fill flex md-swipe-left='next()' md-swipe-right='prev()'><md-toolbar><div class='md-toolbar-tools' layout='row'><md-button ng-click='prev()'>&laquo;</md-button><div flex></div><h2 class='calendar-md-title'><span>{{ calendar.start | date:titleFormat:timezone }}</span></h2><div flex></div><md-button ng-click='next()'>&raquo;</md-button></div></md-toolbar><!-- agenda view --><md-content ng-if='weekLayout === columnWeekLayout' class='agenda'><div ng-repeat='week in calendar.weeks track by $index'><div ng-if='sameMonth(day)' ng-class='{ active: active === day }' ng-click='handleDayClick(day)' ng-repeat='day in week' layout><md-tooltip>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip><div>{{ day | date:dayFormat:timezone }}</div><div flex ng-bind-html='getDayContent(day)'></div></div></div></md-content><!-- calendar view --><md-content ng-if='weekLayout !== columnWeekLayout' flex layout='column' class='calendar'><div ng-if='weekLayout != columnWeekLayout' layout='row' layout-fill class='subheader'><div layout-padding class='subheader-day' flex ng-repeat='day in calendar.weeks[0]'><md-tooltip>{{ day | date:dayLabelTooltipFormat:timezone }}</md-tooltip>{{ day | date:dayLabelFormat:timezone }}</div></div><div ng-if='weekLayout != columnWeekLayout' ng-repeat='week in calendar.weeks track by $index' flex layout='row' layout-fill><div tabindex='{{ sameMonth(day) ? (day | date:dayFormat:timezone) : 0 }}' ng-repeat='day in week track by $index' ng-click='handleDayClick(day)' flex layout layout-padding ng-class='{&quot;disabled&quot; : ! sameMonth(day), &quot;active&quot;: isActive(day), &quot;md-whiteframe-12dp&quot;: hover || focus }' ng-focus='focus = true;' ng-blur='focus = false;' ng-mouseleave='hover = false' ng-mouseenter='hover = true'><md-tooltip>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip><div>{{ day | date:dayFormat:timezone }}</div><div flex ng-bind-html='getDayContent(day)'></div></div></div></md-content></md-content>
1+
<md-content layout='column' layout-fill flex md-swipe-left='next()' md-swipe-right='prev()'><md-toolbar><div class='md-toolbar-tools' layout='row'><md-button ng-click='prev()' aria-label='Previous month'><md-tooltip ng-if='::tooltips()'>Previous month</md-tooltip>&laquo;</md-button><div flex></div><h2 class='calendar-md-title'><span>{{ calendar.start | date:titleFormat:timezone }}</span></h2><div flex></div><md-button ng-click='next()' aria-label='Next month'><md-tooltip ng-if='::tooltips()'>Next month</md-tooltip>&raquo;</md-button></div></md-toolbar><!-- agenda view --><md-content ng-if='weekLayout === columnWeekLayout' class='agenda'><div ng-repeat='week in calendar.weeks track by $index'><div ng-if='sameMonth(day)' ng-class='{ active: active === day }' ng-click='handleDayClick(day)' ng-repeat='day in week' layout><md-tooltip ng-if='::tooltips()'>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip><div>{{ day | date:dayFormat:timezone }}</div><div flex ng-bind-html='getDayContent(day)'></div></div></div></md-content><!-- calendar view --><md-content ng-if='weekLayout !== columnWeekLayout' flex layout='column' class='calendar'><div layout='row' layout-fill class='subheader'><div layout-padding class='subheader-day' flex ng-repeat='day in calendar.weeks[0]'><md-tooltip ng-if='::tooltips()'>{{ day | date:dayLabelTooltipFormat:timezone }}</md-tooltip>{{ day | date:dayLabelFormat:timezone }}</div></div><div ng-if='week.length' ng-repeat='week in calendar.weeks track by $index' flex layout='row' layout-fill><div tabindex='{{ sameMonth(day) ? (day | date:dayFormat:timezone) : 0 }}' ng-repeat='day in week track by $index' ng-click='handleDayClick(day)' flex layout layout-padding ng-class='{&quot;disabled&quot; : ! sameMonth(day), &quot;active&quot;: isActive(day), &quot;md-whiteframe-12dp&quot;: hover || focus }' ng-focus='focus = true;' ng-blur='focus = false;' ng-mouseleave='hover = false' ng-mouseenter='hover = true'><md-tooltip ng-if='::tooltips()'>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip><div>{{ day | date:dayFormat:timezone }}</div><div flex ng-bind-html='data[dayKey(day)]'></div></div></div></md-content></md-content>

dist/angular-material-calendar.js

Lines changed: 402 additions & 1 deletion
Large diffs are not rendered by default.

gulpfile.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ var autoprefixer = require("gulp-autoprefixer");
77
var runSequence = require("run-sequence");
88
var connect = require("gulp-connect");
99
var gfi = require("gulp-file-insert");
10-
var uglify = require("gulp-uglify");
10+
// var uglify = require("gulp-uglify");
1111
var eslint = require("gulp-eslint");
1212
var size = require("gulp-size");
1313
var replace = require("gulp-replace");
@@ -27,7 +27,7 @@ gulp.task("js", function() {
2727
"/* angular-material-calendar.html */": p("dist/angular-material-calendar.html"),
2828
"/* angular-material-calendar.css */": p("dist/angular-material-calendar.css")
2929
}))
30-
.pipe(uglify())
30+
// .pipe(uglify())
3131
.pipe(size({ gzip: true, prettySize: true }))
3232
.pipe(gulp.dest("dist"));
3333
});
@@ -83,7 +83,7 @@ gulp.task("test", ["js:lint-ci"], function() {
8383
});
8484

8585
gulp.task("build", function() {
86-
return runSequence(["scss"], "html", "js");
86+
runSequence("scss", "html", "js");
8787
});
8888

8989
gulp.task("connect", function() {
@@ -94,4 +94,4 @@ gulp.task("watch", function() {
9494
gulp.watch(p("src/**/*"), ["js:lint", "build"]);
9595
});
9696

97-
gulp.task("default", ["build", "karma:tdd", "connect", "watch"]);
97+
gulp.task("default", ["karma:tdd", "connect", "watch"]);

src/angular-material-calendar.html

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,42 @@
11
<md-content layout='column' layout-fill flex md-swipe-left='next()' md-swipe-right='prev()'>
22
<md-toolbar>
33
<div class='md-toolbar-tools' layout='row'>
4-
<md-button ng-click='prev()'>&laquo;</md-button>
4+
<md-button ng-click='prev()' aria-label="Previous month">
5+
<md-tooltip ng-if="::tooltips()">Previous month</md-tooltip>
6+
&laquo;
7+
</md-button>
58
<div flex></div>
69
<h2 class='calendar-md-title'><span>{{ calendar.start | date:titleFormat:timezone }}</span></h2>
710
<div flex></div>
8-
<md-button ng-click='next()'>&raquo;</md-button>
11+
<md-button ng-click='next()' aria-label="Next month">
12+
<md-tooltip ng-if="::tooltips()">Next month</md-tooltip>
13+
&raquo;
14+
</md-button>
915
</div>
1016
</md-toolbar>
1117
<!-- agenda view -->
1218
<md-content ng-if='weekLayout === columnWeekLayout' class='agenda'>
1319
<div ng-repeat='week in calendar.weeks track by $index'>
1420
<div ng-if="sameMonth(day)" ng-class='{ active: active === day }' ng-click='handleDayClick(day)' ng-repeat='day in week' layout>
15-
<md-tooltip>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip>
21+
<md-tooltip ng-if="::tooltips()">{{ day | date:dayTooltipFormat:timezone }}</md-tooltip>
1622
<div>{{ day | date:dayFormat:timezone }}</div>
1723
<div flex ng-bind-html='getDayContent(day)'></div>
1824
</div>
1925
</div>
2026
</md-content>
2127
<!-- calendar view -->
2228
<md-content ng-if='weekLayout !== columnWeekLayout' flex layout="column" class='calendar'>
23-
<div ng-if='weekLayout != columnWeekLayout' layout='row' layout-fill class='subheader'>
29+
<div layout='row' layout-fill class='subheader'>
2430
<div layout-padding class='subheader-day' flex ng-repeat='day in calendar.weeks[0]'>
25-
<md-tooltip>{{ day | date:dayLabelTooltipFormat:timezone }}</md-tooltip>
31+
<md-tooltip ng-if="::tooltips()">{{ day | date:dayLabelTooltipFormat:timezone }}</md-tooltip>
2632
{{ day | date:dayLabelFormat:timezone }}
2733
</div>
2834
</div>
29-
<div ng-if='weekLayout != columnWeekLayout' ng-repeat='week in calendar.weeks track by $index' flex layout='row' layout-fill>
35+
<div ng-if='week.length' ng-repeat='week in calendar.weeks track by $index' flex layout='row' layout-fill>
3036
<div tabindex='{{ sameMonth(day) ? (day | date:dayFormat:timezone) : 0 }}' ng-repeat='day in week track by $index' ng-click='handleDayClick(day)' flex layout layout-padding ng-class='{"disabled" : ! sameMonth(day), "active": isActive(day), "md-whiteframe-12dp": hover || focus }' ng-focus='focus = true;' ng-blur='focus = false;' ng-mouseleave="hover = false" ng-mouseenter="hover = true">
31-
<md-tooltip>{{ day | date:dayTooltipFormat:timezone }}</md-tooltip>
37+
<md-tooltip ng-if="::tooltips()">{{ day | date:dayTooltipFormat:timezone }}</md-tooltip>
3238
<div>{{ day | date:dayFormat:timezone }}</div>
33-
<div flex ng-bind-html="getDayContent(day)"></div>
39+
<div flex ng-bind-html='data[dayKey(day)]'></div>
3440
</div>
3541
</div>
3642
</md-content>

src/angular-material-calendar.js

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ angular.module("materialCalendar").filter("dateToGmt", function() {
77
};
88
});
99

10-
angular.module("materialCalendar").config(["$logProvider", "$compileProvider", function($logProvider, $compileProvider) {
11-
if (document.domain.indexOf("localhost") < 0) {
10+
angular.module("materialCalendar").constant("config", {
11+
version: "0.2.9",
12+
debug: document.domain.indexOf("localhost") > -1
13+
});
14+
15+
angular.module("materialCalendar").config(["config", "$logProvider", "$compileProvider", function(config, $logProvider, $compileProvider) {
16+
if (config.debug) {
1217
$logProvider.debugEnabled(false);
1318
$compileProvider.debugInfoEnabled(false);
1419
}
@@ -41,7 +46,7 @@ angular.module("materialCalendar").service("Calendar", ["$filter", function($fil
4146
this.options = angular.isObject(options) ? options : {};
4247
this.year = now.getFullYear();
4348
this.month = now.getMonth();
44-
this.dates = [];
49+
this.weeks = [];
4550
this.weekStartsOn = this.setWeekStartsOn(this.options.weekStartsOn);
4651

4752
this.getFirstDayOfCalendar = function() {
@@ -93,7 +98,6 @@ angular.module("materialCalendar").service("Calendar", ["$filter", function($fil
9398

9499
// Set up the new date.
95100
this.start = $filter("dateToGmt")(new Date(this.year, this.month, 1, 0, 0));
96-
this.dates = [];
97101
this.weeks = [];
98102

99103
// Reset the month and year to handle the case of many
@@ -124,12 +128,16 @@ angular.module("materialCalendar").service("Calendar", ["$filter", function($fil
124128
}
125129
}
126130

127-
this.dates.push(date);
128131
this.weeks[this.weeks.length - 1].push(date);
129132

130133
}
131134

132-
return this.dates;
135+
// Sanity check to prevent empty weeks.
136+
for (var x = this.weeks.length - 1; x >= 0; --x) {
137+
if (this.weeks[x].length === 0) {
138+
this.weeks.splice(x, 1);
139+
}
140+
}
133141

134142
};
135143

@@ -141,7 +149,7 @@ angular.module("materialCalendar").service("Calendar", ["$filter", function($fil
141149

142150
}]);
143151

144-
angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse", "$http", "$q", "$filter", "$log", "Calendar", function($compile, $parse, $http, $q, $filter, $log, Calendar) {
152+
angular.module("materialCalendar").directive("calendarMd", ["$compile", "$timeout", "$parse", "$http", "$q", "$filter", "$log", "Calendar", function($compile, $timeout, $parse, $http, $q, $filter, $log, Calendar) {
145153

146154
var hasCss;
147155
var defaultTemplate = "/* angular-material-calendar.html */";
@@ -175,7 +183,8 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse"
175183
dayLabelFormat: "=?",
176184
dayLabelTooltipFormat: "=?",
177185
dayTooltipFormat: "=?",
178-
weekStartsOn: "=?"
186+
weekStartsOn: "=?",
187+
tooltips: "&?"
179188
},
180189
link: function($scope, $element, $attrs) {
181190

@@ -210,7 +219,6 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse"
210219
$scope.dayLabelTooltipFormat = $scope.dayLabelTooltipFormat || "EEEE";
211220
$scope.dayFormat = $scope.dayFormat || "d";
212221
$scope.dayTooltipFormat = $scope.dayTooltipFormat || "fullDate";
213-
//$scope.getDayContent = $scope.dayContent || angular.noop;
214222

215223
$scope.sameMonth = function(date) {
216224
var d = $filter("dateToGmt")(date);
@@ -263,6 +271,7 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse"
263271
year: $scope.calendar.year,
264272
month: $scope.calendar.month + 1
265273
};
274+
setData();
266275
handleCb($scope.onPrevMonth, data);
267276
};
268277

@@ -272,12 +281,10 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse"
272281
year: $scope.calendar.year,
273282
month: $scope.calendar.month + 1
274283
};
284+
setData();
275285
handleCb($scope.onNextMonth, data);
276286
};
277287

278-
279-
280-
281288
$scope.handleDayClick = function(date) {
282289

283290
var active = angular.copy($scope.active);
@@ -334,16 +341,51 @@ angular.module("materialCalendar").directive("calendarMd", ["$compile", "$parse"
334341

335342
};
336343

344+
345+
// Set the html contents of each date.
346+
var getDayKey = function(date) {
347+
return [date.getFullYear(), date.getMonth() + 1, date.getDate()].join("-");
348+
};
349+
337350
$scope.data = {};
338-
$scope.getDayContent = function(date) {
339-
if ("undefined" === typeof $scope.data[date.valueOf()]) {
340-
$scope.data[date.valueOf()] = ($scope.dayContent() || angular.noop)(date) || "";
351+
$scope.dayKey = getDayKey;
352+
353+
var getDayContent = function(date) {
354+
355+
// Make sure some data in the data array.
356+
$scope.data[getDayKey(date)] = $scope.data[getDayKey(date)] || "";
357+
358+
var cb = ($scope.dayContent || angular.noop)();
359+
var result = (cb || angular.noop)(date);
360+
361+
// Check for async function. This should support $http.get() and also regular $q.defer() functions.
362+
if (angular.isObject(result) && "function" === typeof result.success) {
363+
result.success(function(html) {
364+
$scope.data[getDayKey(date)] = html;
365+
});
366+
} else if (angular.isObject(result) && "function" === typeof result.then) {
367+
result.then(function(html) {
368+
$scope.data[getDayKey(date)] = html;
369+
});
370+
} else {
371+
$scope.data[getDayKey(date)] = result;
341372
}
342-
return $scope.data[date.valueOf()];
373+
343374
};
344375

376+
var setData = function() {
377+
angular.forEach($scope.calendar.weeks, function(week) {
378+
angular.forEach(week, getDayContent);
379+
});
380+
};
381+
382+
window.data = $scope.data;
383+
345384
var bootstrap = function() {
346-
init().then(setTemplate);
385+
init().then(function(contents) {
386+
setTemplate(contents);
387+
setData();
388+
});
347389
};
348390

349391
$scope.$watch("weekStartsOn", init);

test/unit/calendarMdDirective.spec.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ describe("calendar service", function() {
66
var $rootScope;
77
var $httpBackend;
88
var customTemplateUrl = "/a/custom/template";
9+
var customTemplateContents = "<p>This is a custom template loaded via $http</p>";
910

1011
beforeEach(module("materialCalendar"));
1112

@@ -16,7 +17,7 @@ describe("calendar service", function() {
1617
$httpBackend = $injector.get("$httpBackend");
1718
$httpBackend
1819
.when("GET", customTemplateUrl)
19-
.respond("<p>This is a custom template loaded via $http</p>");
20+
.respond(customTemplateContents);
2021

2122
}));
2223

@@ -29,7 +30,7 @@ describe("calendar service", function() {
2930
$rootScope.$digest();
3031
$httpBackend.flush();
3132

32-
expect(element.html()).toContain("This is a custom template loaded via $http");
33+
expect(element.html()).toContain(customTemplateContents);
3334

3435
});
3536

test/unit/calendarService.spec.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,18 @@ describe("calendar service", function() {
2929
expect(angular.isNumber(Calendar.year)).toBe(true);
3030
expect(angular.isNumber(Calendar.month)).toBe(true);
3131
expect(angular.isNumber(Calendar.weekStartsOn)).toBe(true);
32-
expect(angular.isArray(Calendar.dates)).toBe(true);
32+
expect(angular.isArray(Calendar.weeks)).toBe(true);
33+
});
34+
35+
it("should start with the correct dates in February 2015", function() {
36+
Calendar.init(2015, 1);
37+
expect(angular.equals(Calendar.start, $date(2015, 1, 1))).toBe(true);
38+
expect(angular.equals(Calendar.weeks[0][0], $date(2015, 1, 1))).toBe(true);
39+
});
40+
41+
it("should contain the correct number of weeks in February 2015", function() {
42+
Calendar.init(2015, 1);
43+
expect(Calendar.weeks.length).toBe(4);
3344
});
3445

3546
it("should start with the correct dates in October 2015", function() {
@@ -38,18 +49,33 @@ describe("calendar service", function() {
3849
expect(angular.equals(Calendar.weeks[0][0], $date(2015, 8, 27))).toBe(true);
3950
});
4051

52+
it("should contain the correct number of weeks in October 2015", function() {
53+
Calendar.init(2015, 9);
54+
expect(Calendar.weeks.length).toBe(6);
55+
});
56+
4157
it("should start with the correct dates in November 2015", function() {
4258
Calendar.init(2015, 10);
4359
expect(angular.equals(Calendar.start, $date(2015, 10, 1))).toBe(true);
4460
expect(angular.equals(Calendar.weeks[0][0], $date(2015, 10, 1))).toBe(true);
4561
});
4662

63+
it("should contain the correct number of weeks in November 2015", function() {
64+
Calendar.init(2015, 10);
65+
expect(Calendar.weeks.length).toBe(5);
66+
});
67+
4768
it("should start with the correct dates in July 2016", function() {
4869
Calendar.init(2016, 6);
4970
expect(angular.equals(Calendar.start, $date(2016, 6, 1))).toBe(true);
5071
expect(angular.equals(Calendar.weeks[0][0], $date(2016, 5, 26))).toBe(true);
5172
});
5273

74+
it("should contain the correct number of weeks in November 2015", function() {
75+
Calendar.init(2016, 6);
76+
expect(Calendar.weeks.length).toBe(6);
77+
});
78+
5379
it("should start with the correct dates in March 2017", function() {
5480
Calendar.init(2017, 2);
5581
expect(angular.equals(Calendar.start, $date(2017, 2, 1))).toBe(true);

website/fullscreen.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
day-label-tooltip-format="'EEEE'"
4949
day-tooltip-format="'fullDate'"
5050
week-starts-on="weekStartsOn"
51+
tooltips="tooltips"
5152
day-content="setDayContent"></calendar-md>
5253
</md-content>
5354
<script src="js/angular.min.js"></script>

0 commit comments

Comments
 (0)