Skip to content

Commit

Permalink
better handling of year and month custom views
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Dec 29, 2014
1 parent fabf5a6 commit f90476a
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 60 deletions.
1 change: 0 additions & 1 deletion src/agenda/AgendaView.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ fcViews.agenda = View.extend({ // AgendaView

if (this.opt('allDaySlot')) { // should we display the "all-day" area?
this.dayGrid = new DayGrid(this); // the all-day subcomponent of this view
this.dayGrid.breakOnWeeks = false;

// the coordinate grid will be a combination of both subcomponents' grids
this.coordMap = new ComboCoordMap([
Expand Down
22 changes: 22 additions & 0 deletions src/basic/BasicView.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,32 @@ var BasicView = fcViews.basic = View.extend({
// Sets the display range and computes all necessary dates
setRange: function(range) {
View.prototype.setRange.call(this, range); // call the super-method

this.dayGrid.breakOnWeeks = /year|month|week/.test(this.intervalUnit); // do before setRange
this.dayGrid.setRange(range);
},


// Compute the value to feed into setRange. Overrides superclass.
computeRange: function(date) {
var range = View.prototype.computeRange.call(this, date); // get value from the super-method

// year and month views should be aligned with weeks. this is already done for week
if (/year|month/.test(range.intervalUnit)) {
range.start.startOf('week');
range.start = this.skipHiddenDays(range.start);

// make end-of-week if not already
if (range.end.weekday()) {
range.end.add(1, 'week').startOf('week');
range.end = this.skipHiddenDays(range.end, -1, true); // exclusively move backwards
}
}

return range;
},


// Renders the view into `this.el`, which should already be assigned
render: function() {

Expand Down
41 changes: 12 additions & 29 deletions src/basic/MonthView.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,21 @@ setDefaults({
fixedWeekCount: true
});

fcViews.month = BasicView.extend({ // MonthView
var MonthView = fcViews.month = BasicView.extend({

// Produces information about what range to display
computeRange: function(date) {
var rowCnt;
var intervalStart, intervalEnd;
var start, end;

intervalStart = date.clone().stripTime().startOf('month');
intervalEnd = intervalStart.clone().add(1, 'months');

start = intervalStart.clone();
start = this.skipHiddenDays(start); // move past the first week if no visible days
start.startOf('week');
start = this.skipHiddenDays(start); // move past the first invisible days of the week

end = intervalEnd.clone();
end = this.skipHiddenDays(end, -1, true); // move in from the last week if no visible days
end.add((7 - end.weekday()) % 7, 'days'); // move to end of week if not already
end = this.skipHiddenDays(end, -1, true); // move in from the last invisible days of the week

rowCnt = Math.ceil( // need to ceil in case there are hidden days
end.diff(start, 'weeks', true) // returnfloat=true
);
var range = BasicView.prototype.computeRange.call(this, date); // get value from super-method

if (this.isFixedWeeks()) {
end.add(6 - rowCnt, 'weeks');
rowCnt = 6;
// ensure 6 weeks
range.end.add(
6 - range.end.diff(range.start, 'weeks'),
'weeks'
);
}

return {
start: start,
end: end,
intervalStart: intervalStart,
intervalEnd: intervalEnd
};
return range;
},


Expand Down Expand Up @@ -67,3 +48,5 @@ fcViews.month = BasicView.extend({ // MonthView
}

});

MonthView.duration = { months: 1 };
9 changes: 2 additions & 7 deletions src/common/DayGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var DayGrid = Grid.extend({

numbersVisible: false, // should render a row for day/week numbers? set by outside view. TODO: make internal
bottomCoordPadding: 0, // hack for extending the hit area for the last row of the coordinate grid
breakOnWeeks: null, // allows the outside view to override this rendering setting
breakOnWeeks: null, // should create a new row for each week? set by outside view

cellDates: null, // flat chronological array of each cell's dates
dayToCellOffsets: null, // maps days offsets from grid's start date, to cell offsets
Expand Down Expand Up @@ -126,20 +126,15 @@ var DayGrid = Grid.extend({

// Initializes row/col information
updateCells: function() {
var breakOnWeeks = this.breakOnWeeks; // look at the override first
var cellDates;
var firstDay;
var rowCnt;
var colCnt;

if (breakOnWeeks == null) { // not overridden. compute it
breakOnWeeks = /year|month|week/.test(this.view.intervalUnit);
}

this.updateCellDates(); // populates cellDates and dayToCellOffsets
cellDates = this.cellDates;

if (breakOnWeeks) {
if (this.breakOnWeeks) {
// count columns until the day-of-week repeats
firstDay = cellDates[0].day();
for (colCnt = 1; colCnt < cellDates.length; colCnt++) {
Expand Down
43 changes: 20 additions & 23 deletions src/common/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,48 +109,45 @@ var View = fc.View = Class.extend({
// Updates all internal dates for displaying the given range.
// Expects all values to be normalized (like what computeRange does).
setRange: function(range) {
this.start = range.start;
this.end = range.end;

// all interval-related is computed if not explicitly provided by computeRange
this.intervalStart = range.intervalStart || range.start.clone();
this.intervalEnd = range.intervalEnd || range.end.clone();
this.intervalDuration = range.intervalDuration || computeIntervalDuration(this.intervalStart, this.intervalEnd);
this.intervalUnit = range.intervalUnit || computeIntervalUnit(this.intervalDuration);
$.extend(this, range);
},


// Given a single current, produce information about what range to display.
// Subclasses can override. Must return {start,end} at the very least.
// Given a single current date, produce information about what range to display.
// Subclasses can override. Must return all properties.
computeRange: function(date) {
var intervalDuration = moment.duration(this.opt('duration') || { days: 1 });
var intervalDuration = moment.duration(this.opt('duration') || this.constructor.duration || { days: 1 });
var intervalUnit = computeIntervalUnit(intervalDuration);
var start = date.clone().startOf(intervalUnit);
var end = start.clone().add(intervalDuration);
var intervalStart = date.clone().startOf(intervalUnit);
var intervalEnd = intervalStart.clone().add(intervalDuration);
var start, end;

// normalize the range's time-ambiguity
if (computeIntervalAs('days', intervalDuration)) { // whole-days?
start.stripTime();
end.stripTime();
intervalStart.stripTime();
intervalEnd.stripTime();
}
else { // needs to have a time?
if (!start.hasTime()) {
start = this.calendar.rezoneDate(start); // convert to current timezone, with a 00:00 time
if (!intervalStart.hasTime()) {
intervalStart = this.calendar.rezoneDate(intervalStart); // convert to current timezone, with 00:00
}
if (!end.hasTime()) {
end = this.calendar.rezoneDate(end); // convert to current timezone, with a 00:00 time
if (!intervalEnd.hasTime()) {
intervalEnd = this.calendar.rezoneDate(intervalEnd); // convert to current timezone, with 00:00
}
}

// trim the range's edges for hidden days
start = intervalStart.clone();
start = this.skipHiddenDays(start);
end = intervalEnd.clone();
end = this.skipHiddenDays(end, -1, true); // exclusively move backwards

return {
start: start,
end: end,
intervalDuration: intervalDuration,
intervalUnit: intervalUnit
intervalUnit: intervalUnit,
intervalStart: intervalStart,
intervalEnd: intervalEnd,
start: start,
end: end
};
},

Expand Down
2 changes: 2 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ function diffDay(a, b) {
// Computes the larges whole-unit period of time, as a duration object.
// For example, 48 hours will be {days:2} whereas 49 hours will be {hours:49}.
// Accepts start/end, a range object, or an original duration object.
/* (never used)
function computeIntervalDuration(start, end) {
var durationInput = {};
var i, unit;
Expand All @@ -302,6 +303,7 @@ function computeIntervalDuration(start, end) {
durationInput[unit] = val;
return moment.duration(durationInput);
}
*/


// Computes the unit name of the largest whole-unit period of time.
Expand Down
41 changes: 41 additions & 0 deletions tests/automated/custom-view-duration.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,45 @@ describe('custom view duration', function() {
expect($('.fc-time-grid .fc-day').length).toBe(14);
expect($('.fc-time-grid .fc-day:first')).toBeMatchedBy('[data-date="2014-12-21"]'); // week start
});

it('renders a two month agenda view', function() {
options.views.agendaTwoMonth = {
type: 'agenda',
duration: { months: 2 }
};
options.defaultView = 'agendaTwoMonth';
options.defaultDate = '2014-11-27';
$('#cal').fullCalendar(options);
expect($('.fc-day-grid .fc-row').length).toBe(1);
expect($('.fc-day-grid .fc-row .fc-day').length).toBe(61); // one long row
expect($('.fc-time-grid .fc-day').length).toBe(61);
expect($('.fc-time-grid .fc-day:first')).toBeMatchedBy('[data-date="2014-11-01"]');
expect($('.fc-time-grid .fc-day:last')).toBeMatchedBy('[data-date="2014-12-31"]');
});

it('renders a two month basic view', function() {
options.views.basicTwoWeek = {
type: 'basic',
duration: { months: 2 }
};
options.defaultView = 'basicTwoWeek';
options.defaultDate = '2014-11-27';
$('#cal').fullCalendar(options);
expect($('.fc-day-grid .fc-row').length).toBe(10);
expect($('.fc-day-grid .fc-row:first .fc-day').length).toBe(7);
expect($('.fc-day-grid .fc-day:first')).toBeMatchedBy('[data-date="2014-10-26"]');
expect($('.fc-day-grid .fc-day:last')).toBeMatchedBy('[data-date="2015-01-03"]');
});

it('renders a one year basic view', function() {
options.views.basicYear = {
type: 'basic',
duration: { years: 1 }
};
options.defaultView = 'basicYear';
options.defaultDate = '2014-11-27';
$('#cal').fullCalendar(options);
expect($('.fc-day-grid .fc-day:first')).toBeMatchedBy('[data-date="2013-12-29"]');
expect($('.fc-day-grid .fc-day:last')).toBeMatchedBy('[data-date="2015-01-03"]');
});
});

0 comments on commit f90476a

Please sign in to comment.