Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Replace jquery with querySelector and domify, classes and delegate components #24

Closed
wants to merge 5 commits into from

3 participants

@uggedal

An alternative to the incomplete removal of jQuery in #20 and the more verbose jQuery removal in #21.

Only IE9+ support due to textContent but the existing implementation was using Array.prototype.map so I did not fall back to innerText. Could probably be solved with a separate component or changes to dom's text() if IE8 support is important. I opted to use event in stead of a straight addEventListener since I already pulled in delegate.

@cgarvis

+1

@tj
Owner
tj commented

calendar has enough stuff I think it would be worth using component/dom

@uggedal uggedal closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 21, 2013
  1. @uggedal
Commits on Feb 26, 2013
  1. @uggedal

    Fix js references in Makefile.

    uggedal authored
  2. @uggedal
  3. @uggedal
Commits on Mar 5, 2013
  1. @uggedal

    Fix for..in with arrays.

    uggedal authored
This page is out of date. Refresh to see the latest.
View
4 Makefile
@@ -1,8 +1,8 @@
SRC = index.js \
lib/template.js \
- lib/Calendar.js \
- lib/Days.js \
+ lib/calendar.js \
+ lib/days.js \
lib/calendar.css
build: components $(SRC)
View
6 component.json
@@ -10,8 +10,10 @@
],
"dependencies": {
"component/range": "*",
- "component/jquery": "*",
"component/emitter": "*",
+ "component/domify": "*",
+ "component/classes": "*",
+ "component/delegates": "*",
"component/in-groups-of": "*"
},
"development": {
@@ -28,4 +30,4 @@
"lib/days.js"
],
"license": "MIT"
-}
+}
View
10 example.html
@@ -48,7 +48,7 @@
console.log('change %s', action);
var twoDate = new Date(date);
twoDate.setMonth(date.getMonth() + 1)
- two.show(twoDate);
+ small.show(twoDate);
});
one.on('change', function(date){
@@ -58,19 +58,19 @@
date.getFullYear());
var newDate = new Date(date);
newDate.setMonth(date.getMonth() + 1);
- two.select(newDate);
+ small.select(newDate);
});
- one.el.appendTo('body');
+ document.body.appendChild(one.el);
var small = new Calendar;
small.addClass('small');
- small.el.appendTo('body');
+ document.body.appendChild(small.el);
small.next();
var large = new Calendar;
large.addClass('large');
- large.el.appendTo('body');
+ document.body.appendChild(large.el);
</script>
</body>
</html>
View
19 lib/calendar.js
@@ -3,7 +3,8 @@
* Module dependencies.
*/
-var o = require('jquery')
+var domify = require('domify')
+ , classes = require('classes')
, Emitter = require('emitter')
, template = require('./template')
, Days = require('./days')
@@ -33,9 +34,9 @@ module.exports = Calendar;
function Calendar(date) {
Emitter.call(this);
var self = this;
- this.el = o('<div class=calendar></div>');
+ this.el = domify('<div class=calendar></div>')[0];
this.days = new Days;
- this.el.append(this.days.el);
+ this.el.appendChild(this.days.el);
this.on('change', this.show.bind(this));
this.days.on('prev', this.prev.bind(this));
this.days.on('next', this.next.bind(this));
@@ -64,7 +65,7 @@ Emitter(Calendar.prototype);
*/
Calendar.prototype.addClass = function(name){
- this.el.addClass(name);
+ classes(this.el).add(name);
return this;
};
@@ -194,3 +195,13 @@ Calendar.prototype.menuChange = function(action){
this.emit('view change', date, action);
return this;
};
+
+/**
+ * Unbind DOM event handlers.
+ *
+ * @api public
+ */
+
+Calendar.prototype.unbind = function(){
+ this.days.unbind();
+};
View
185 lib/days.js
@@ -3,12 +3,14 @@
* Module dependencies.
*/
-var o = require('jquery')
+var domify = require('domify')
+ , classes = require('classes')
, Emitter = require('emitter')
+ , delegates = require('delegates')
, template = require('./template')
, inGroupsOf = require('in-groups-of')
, clamp = require('./utils').clamp
- , range = require('range')
+ , range = require('range');
/**
* Days.
@@ -68,40 +70,17 @@ module.exports = Days;
function Days() {
Emitter.call(this);
- var self = this;
- this.el = o(template).addClass('calendar-days');
- this.head = this.el.find('thead');
- this.body = this.el.find('tbody');
- this.title = this.head.find('.title');
+ this.el = classes(domify(template)[0]).add('calendar-days').el;
+ this.head = this.el.querySelector('thead');
+ this.body = this.el.querySelector('tbody');
+ this.title = this.head.querySelector('.title');
this.select(new Date);
- // emit "day"
- this.body.on('click', 'a', function(e){
- var el = o(e.target);
- var day = parseInt(el.text(), 10);
- var data = el.data('date').split('-');
- var year = data[0];
- var month = data[1];
- var date = new Date;
- date.setYear(year);
- date.setMonth(month);
- date.setDate(day);
- self.select(date);
- self.emit('change', date);
- return false;
- });
-
- // emit "prev"
- this.el.find('.prev').click(function(){
- self.emit('prev');
- return false;
- });
-
- // emit "next"
- this.el.find('.next').click(function(){
- self.emit('next');
- return false;
- });
+ this.headDelegates = delegates(this.head, this);
+ this.headDelegates.bind('click a', 'onMonthPaginationClick');
+
+ this.bodyDelegates = delegates(this.body, this);
+ this.bodyDelegates.bind('click a', 'onDayClick');
}
/**
@@ -111,6 +90,17 @@ function Days() {
Emitter(Days.prototype);
/**
+ * Unbind DOM event handlers.
+ *
+ * @api public
+ */
+
+Days.prototype.unbind = function(){
+ this.headDelegates.unbind();
+ this.bodyDelegates.unbind();
+};
+
+/**
* Select the given `date`.
*
* @param {Date} date
@@ -135,10 +125,13 @@ Days.prototype.show = function(date){
var month = date.getMonth();
this.showSelectedYear(year);
this.showSelectedMonth(month);
- this.head.find('.subheading').remove();
- this.head.append(this.renderHeading(2));
- this.body.empty();
- this.body.append(this.renderDays(date));
+ var subheading = this.head.querySelector('.subheading');
+ if (subheading) subheading.parentNode.removeChild(subheading);
+ this.head.appendChild(this.renderHeading(2));
+ this.body.innerHTML = '';
+ this.renderDays(date).forEach(function(day) {
+ this.body.appendChild(day);
+ }, this);
};
/**
@@ -151,12 +144,8 @@ Days.prototype.show = function(date){
Days.prototype.yearMenu = 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('year');
- return false;
- });
+ this.title.querySelector('.year').innerHTML = yearDropdown(from, to);
+ this.headDelegates.bind('change .year .calendar-select', 'onYearMenuChange');
};
/**
@@ -167,12 +156,8 @@ Days.prototype.yearMenu = function(from, to){
Days.prototype.monthMenu = function(){
this.selectMonth = true;
- this.title.find('.month').html(monthDropdown());
- var self = this;
- this.title.find('.month .calendar-select').change(function(){
- self.emit('month');
- return false;
- });
+ this.title.querySelector('.month').innerHTML = monthDropdown();
+ this.headDelegates.bind('change .month .calendar-select', 'onMonthMenuChange');
};
/**
@@ -183,9 +168,9 @@ Days.prototype.monthMenu = function(){
Days.prototype.titleYear = function(){
if (this.selectYear) {
- return this.title.find('.year .calendar-select').val();
+ return this.title.querySelector('.year .calendar-select').value;
} else {
- return this.title.find('.year').text();
+ return this.title.querySelector('.year').textContent;
}
};
@@ -197,9 +182,9 @@ Days.prototype.titleYear = function(){
Days.prototype.titleMonth = function(){
if (this.selectMonth) {
- return this.title.find('.month .calendar-select').val();
+ return this.title.querySelector('.month .calendar-select').value;
} else {
- return this.title.find('.month').text();
+ return this.title.querySelector('.month').textContent;
}
};
@@ -227,7 +212,7 @@ Days.prototype.renderHeading = function(len){
var rows = '<tr class=subheading>' + days.map(function(day){
return '<th>' + day.slice(0, len) + '</th>';
}).join('') + '</tr>';
- return o(rows);
+ return domify(rows)[0];
};
/**
@@ -243,7 +228,7 @@ Days.prototype.renderDays = function(date){
var html = rows.map(function(row){
return '<tr>' + row.join('') + '</tr>';
}).join('\n');
- return o(html);
+ return domify(html);
};
/**
@@ -252,7 +237,7 @@ Days.prototype.renderDays = function(date){
* This method calculates the "overflow"
* from the previous month and into
* the next in order to display an
- * even 5 rows.
+ * even 5 rows.
*
* @param {Date} date
* @return {Array}
@@ -280,14 +265,14 @@ Days.prototype.rowsFor = function(date){
// cells before
cells = cells.concat(cellsBefore(before, month, year));
- // current cells
+ // current cells
for (var i = 0; i < total; ++i) {
var day = i + 1;
- var date = 'data-date=' + [year, month, day].join('-');
+ var dateData = 'data-date=' + [year, month, day].join('-');
if (day == selectedDay && month == selectedMonth && year == selectedYear) {
- cells.push('<td class=selected><a href="#" ' + date + '>' + day + '</a></td>');
+ cells.push('<td class=selected><a href="#" ' + dateData + '>' + day + '</a></td>');
} else {
- cells.push('<td><a href="#" ' + date + '>' + day + '</a></td>');
+ cells.push('<td><a href="#" ' + dateData + '>' + day + '</a></td>');
}
}
@@ -306,9 +291,9 @@ Days.prototype.rowsFor = function(date){
Days.prototype.showSelectedYear = function(year){
if (this.selectYear) {
- this.title.find('.year .calendar-select').val(year);
+ this.title.querySelector('.year .calendar-select').value = year;
} else {
- this.title.find('.year').text(year);
+ this.title.querySelector('.year').textContent = year;
}
};
@@ -321,13 +306,79 @@ Days.prototype.showSelectedYear = function(year){
Days.prototype.showSelectedMonth = function(month) {
if (this.selectMonth) {
- this.title.find('.month .calendar-select').val(month);
+ this.title.querySelector('.month .calendar-select').value = month;
} else {
- this.title.find('.month').text(months[month]);
+ this.title.querySelector('.month').textContent = months[month];
}
};
/**
+ * Handle click on previous or next month.
+ * Emits prev or next.
+ *
+ * @param {Event} e
+ * @api private
+ */
+
+Days.prototype.onMonthPaginationClick = function(e){
+ e.preventDefault();
+ var el = e.target;
+
+ if (classes(el).has('prev')) return this.emit('prev');
+ if (classes(el).has('next')) return this.emit('next');
+};
+
+/**
+ * Handle click on a day.
+ * Emits the clicked day.
+ *
+ * @param {Event} e
+ * @api private
+ */
+
+Days.prototype.onDayClick = function(e){
+ e.preventDefault();
+ var el = e.target;
+ var day = parseInt(el.textContent, 10);
+ var data = el.getAttribute('data-date').split('-');
+ var year = data[0];
+ var month = data[1];
+ var date = new Date;
+ date.setYear(year);
+ date.setMonth(month);
+ date.setDate(day);
+ this.select(date);
+ this.emit('change', date);
+};
+
+/**
+ * Handle change of year menu.
+ * Emits year.
+ *
+ * @param {Event} e
+ * @api private
+ */
+
+Days.prototype.onYearMenuChange = function(e) {
+ e.preventDefault();
+ this.emit('year');
+}
+
+/**
+ * Handle change of month menu.
+ * Emits year.
+ *
+ * @param {Event} e
+ * @api private
+ */
+
+Days.prototype.onMonthMenuChange = function(e) {
+ e.preventDefault();
+ this.emit('month');
+}
+
+
+/**
* Return `n` days before `month`.
*
* @param {Number} n
@@ -387,7 +438,7 @@ function nextMonthDay(year, month, day) {
function yearDropdown(from, to) {
var years = range(from, to, 'inclusive');
- var options = o.map(years, yearOption).join('');
+ var options = years.map(yearOption).join('');
return '<select class="calendar-select">' + options + '</select>';
}
@@ -396,7 +447,7 @@ function yearDropdown(from, to) {
*/
function monthDropdown() {
- var options = o.map(months, monthOption).join('');
+ var options = months.map(monthOption).join('');
return '<select class="calendar-select">' + options + '</select>';
}
View
6 lib/template.html
@@ -1,11 +1,11 @@
<table class="calendar-table">
<thead>
<tr>
- <td class="prev"><a href="#">←</a></td>
+ <td><a class="prev" href="#">←</a></td>
<td colspan="5" class="title"><span class="month"></span> <span class="year"></span></td>
- <td class="next"><a href="#">→</a></td>
+ <td><a class="next" href="#">→</a></td>
</tr>
</thead>
<tbody>
</tbody>
-</table>
+</table>
View
2  lib/template.js
@@ -1 +1 @@
-module.exports = '<table class="calendar-table">\n <thead>\n <tr>\n <td class="prev"><a href="#">←</a></td>\n <td colspan="5" class="title"><span class="month"></span> <span class="year"></span></td>\n <td class="next"><a href="#">→</a></td>\n </tr>\n </thead>\n <tbody>\n </tbody>\n</table>';
+module.exports = '<table class="calendar-table">\n <thead>\n <tr>\n <td><a class="prev" href="#">←</a></td>\n <td colspan="5" class="title"><span class="month"></span> <span class="year"></span></td>\n <td><a class="next" href="#">→</a></td>\n </tr>\n </thead>\n <tbody>\n </tbody>\n</table>\n';
Something went wrong with that request. Please try again.