Skip to content

Commit

Permalink
Implement month and year selection - relates to issues #2 and #3
Browse files Browse the repository at this point in the history
  • Loading branch information
colinf authored and tj committed Oct 17, 2012
1 parent 4419e81 commit c1cb451
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 6 deletions.
15 changes: 14 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Calendar UI component designed for use as a date-picker,
full-sized calendar or anything in-between.

![javascript calendar component](http://f.cl.ly/items/043N1r0e1L130y162R2f/Screen%20Shot%202012-09-17%20at%209.17.32%20PM.png)
![javascript calendar component](http://f.cl.ly/items/2u3w1D421W0C370Z3G1U/Screen%20Shot%202012-10-11%20at%2014.32.41.png)

## Installation

Expand All @@ -22,6 +22,7 @@ cal.el.appendTo('body');

- `prev` when the prev link is clicked
- `next` when the next link is clicked
- `view change` (date) when the month/year dropdowns are changed
- `change` (date) when the selected date is modified

## API
Expand All @@ -40,6 +41,18 @@ cal.el.appendTo('body');
Show the given `date`. This does _not_ select the given date,
it simply ensures that it is visible in the current view.

### Calendar#canSelectMonth()

Adds a month dropdown to allow jumping to selected month.

### Calendar#selectYear([from], [to])

Adds a year dropdown to allow jumping to selected year. `From` specifies the first year shown in the dropdown and `to` the last year. This means that if `to` is less than `from`, the years will be listed in descending order.

If `from`/`to` are both not specified the dropdown defaults to -/+ 10 years from the calendar's date.

If only `from` specified it defaults `to` +20 years from that year.

### Calendar#prev()

Show the previous view (month).
Expand Down
47 changes: 47 additions & 0 deletions lib/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function Calendar(date) {
this.on('change', this.show.bind(this));
this.days.on('prev', this.prev.bind(this));
this.days.on('next', this.next.bind(this));
this.days.on('view change', this.viewChange.bind(this));
this.show(date || new Date);
this.days.on('change', function(date){
self.emit('change', date);
Expand Down Expand Up @@ -95,6 +96,39 @@ Calendar.prototype.show = function(date){
return this;
};

/**
* Enable a year dropdown.
*
* @param {from} Number
* @param {to} Number
* @return {Calendar}
* @api public
*/

Calendar.prototype.canSelectYear = function(from, to){
if (!from) {
from = this._date.getFullYear() - 10;
to = this._date.getFullYear() + 10;
};
to = to || from + 20;
this.days.canSelectYear(from, to);
this.show(this._date);
return this;
};

/**
* Enable a month dropdown.
*
* @return {Calendar}
* @api public
*/

Calendar.prototype.canSelectMonth = function(){
this.days.canSelectMonth();
this.show(this._date);
return this;
};

/**
* Return the previous month.
*
Expand Down Expand Up @@ -146,3 +180,16 @@ Calendar.prototype.next = function(){
this.emit('next');
return this;
};

/**
* Jump to a date/month (using dropdowns).
*
* @return {Calendar}
* @api public
*/

Calendar.prototype.viewChange = function(date){
this.show(date);
this.emit('view change', date);
return this;
};
145 changes: 143 additions & 2 deletions lib/days.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function Days() {
this.el = o(template).addClass('calendar-days');
this.head = this.el.find('thead');
this.body = this.el.find('tbody');
this.title = this.el.find('.title a');
this.title = this.head.find('.title');
this.select(new Date);

// emit "day"
Expand Down Expand Up @@ -132,13 +132,77 @@ Days.prototype.select = function(date){
Days.prototype.show = function(date){
var year = date.getFullYear();
var month = date.getMonth();
this.title.text(months[month] + ' ' + year);
this.setTitle(year, month);
this.head.find('.subheading').remove();
this.head.append(this.renderHeading(2));
this.body.empty();
this.body.append(this.renderDays(date));
};

/**
* Enable a year dropdown.
*
* @param {Number} from
* @param {Number} to
* @api public
*/

Days.prototype.canSelectYear = function(from, to){
this.selectYear = true;
this.title.find('.year').html(yearDropdown(from, to));
var self = this;
this.title.find('.year .calendar-select').change(function() {
self.emit('view change', new Date(self.titleYear(), self.titleMonth(), 1));
return false;
});

};

/**
* Enable a month dropdown.
*
* @api public
*/

Days.prototype.canSelectMonth = function(){
this.selectMonth = true;
this.title.find('.month').html(monthDropdown());
var self = this;
this.title.find('.month .calendar-select').change(function() {
self.emit('view change', new Date(self.titleYear(), self.titleMonth(), 1));
return false;
});

};

/**
* Return current year of view from title.
*
* @api private
*/

Days.prototype.titleYear = function(){
if (this.selectYear) {
return this.title.find('.year .calendar-select').val();
} else {
return this.title.find('.year').text();
}
};

/**
* Return current month of view from title.
*
* @api private
*/

Days.prototype.titleMonth = function(){
if (this.selectMonth) {
return this.title.find('.month .calendar-select').val();
} else {
return this.title.find('.month').text();
}
};

/**
* Render days of the week heading with
* the given `length`, for example 2 for "Tu",
Expand Down Expand Up @@ -223,6 +287,28 @@ Days.prototype.rowsFor = function(date){
return inGroupsOf(cells, 7);
};

/**
* Update view title for `year` and `month`.
*
* @param {year} number
* @param {month} number
* @return null
* @api private
*/

Days.prototype.setTitle = function(year, month) {
if (this.selectMonth) {
this.title.find('.month .calendar-select').val(month);
} else {
this.title.find('.month').text(months[month]);
};
if (this.selectYear) {
this.title.find('.year .calendar-select').val(year);
} else {
this.title.find('.year').text(year);
};
};

/**
* Return `n` days before `month`.
*
Expand Down Expand Up @@ -277,3 +363,58 @@ function nextMonthDay(year, month, day) {
return '<td><a href="#" ' + date + ' class=next-day>' + day + '</a></td>';
}

/**
* Year dropdown template.
*/

function yearDropdown(from, to) {
var years = range(from, to);
var options = o.map(years, yearOption).join('');
return '<select class="calendar-select">'+options+'</select>';
}

/**
* Month dropdown template.
*/

function monthDropdown() {
var options = o.map(months, monthOption).join('');
return '<select class="calendar-select">'+options+'</select>';
}

/**
* Year dropdown option template.
*/

function yearOption(year) {
return '<option value="'+year+'">'+year+'</option>';
}

/**
* Month dropdown option template.
*/

function monthOption(month, i) {
return '<option value="'+i+'">'+month+'</option>';
}

/**
* Return an array of the values between 2 integers.
* With a blank at the start.
*/

function range(from, to) {
if (from > to) {
var reverseTo = to;
to = from;
from = reverseTo;
};
var rangeArray = [];
rangeArray.push('');
for (var i = from; i <= to; i++) {
rangeArray.push(i);
};
if (reverseTo) rangeArray.reverse();
return rangeArray;
}

2 changes: 1 addition & 1 deletion lib/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<thead>
<tr>
<td class="prev"><a href="#"></a></td>
<td colspan="5" class="title"><a href="#">title</a></td>
<td colspan="5" class="title"><span class="month"></span> <span class="year"></span></td>
<td class="next"><a href="#"></a></td>
</tr>
</thead>
Expand Down
2 changes: 1 addition & 1 deletion lib/template.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ <h1>Calendar</h1>
<script src="../build/build.js"></script>
<script>
var Calendar = require('calendar');
var one = new Calendar;
var one = (new Calendar).canSelectMonth().canSelectYear();

one.on('next', function(){
two.next();
Expand All @@ -33,6 +33,12 @@ <h1>Calendar</h1>
two.prev();
});

one.on('view change', function(date){
var twoDate = new Date(date);
twoDate.setMonth(date.getMonth() + 1)
two.show(twoDate);
});

one.on('change', function(date){
console.log('selected: %s of %s %s',
date.getDate(),
Expand Down

0 comments on commit c1cb451

Please sign in to comment.