Skip to content

Commit

Permalink
Rough non-jQuery version
Browse files Browse the repository at this point in the history
  • Loading branch information
jonthornton committed Jun 20, 2014
1 parent 8ab02ae commit 2cc7618
Show file tree
Hide file tree
Showing 7 changed files with 614 additions and 88 deletions.
43 changes: 41 additions & 2 deletions GruntFile.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
meta: {
banner: '/*!\n' +
' * <%= pkg.name %> v<%= pkg.version %> - <%= pkg.description %>\n' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> - <%= pkg.homepage %>\n' +
' * License: <%= pkg.license %>\n' +
' */\n\n',
outputDir: 'dist',
output: '<%= meta.outputDir %>/<%= pkg.name %>',
outputMin: '<%= meta.outputDir %>/<%= pkg.name.replace("js", "min.js") %>'
},

rig: {
options: {
banner: '<%= meta.banner %>'
},
dist: {
files: {
'<%= meta.output %>': ['src/wrapper.js'],
// 'dist/jQuery.headroom.js' : ['src/jQuery.headroom.js'],
// 'dist/angular.headroom.js' : ['src/angular.headroom.js']
}
}
},

uglify: {
options: {
banner: '<%= meta.banner %>',
report: 'gzip'
},
dist: {
files: {
'jquery.datepair.min.js': ['jquery.datepair.js']
'<%= meta.outputMin %>': '<%= meta.output %>',
}
}
},

watch: {
options : {
atBegin : true
},
files: ['src/*.js'],
tasks: ['rig']
}
});

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
grunt.loadNpmTasks('grunt-rigger');
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.registerTask('default', ['rig', 'uglify']);
};
244 changes: 244 additions & 0 deletions dist/datepair.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*!
* datepair.js v0.1.1 - A jQuery plugin for intelligently selecting date and time ranges inspired by Google Calendar.
* Copyright (c) 2014 Jon Thornton - http://jonthornton.github.com/jquery-datepair/
* License: MIT
*/

(function(window, document) {

'use strict';

function simpleExtend(obj1, obj2) {
var out = obj2 || {};

for (var i in obj1) {
if (!(i in out)) {
out[i] = obj1[i]
}
}

return out;
}

function triggerSimpleCustomEvent(el, eventName) {
if (window.CustomEvent) {
var event = new CustomEvent(eventName);
} else {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true);
}

el.dispatchEvent(event);
}

var _ONE_DAY = 86400000;

function Datepair(container, options) {
this.dateDelta = null;
this.timeDelta = null;
this._defaults = {
startClass: 'start',
endClass: 'end',
timeClass: 'time',
dateClass: 'date',
defaultDateDelta: 0,
defaultTimeDelta: 3600000,

// defaults for jquery-timepicker; override when using other input widgets
parseTime: function(input){
return jQuery(input).timepicker('getTime');
},
updateTime: function(input, dateObj){
jQuery(input).timepicker('setTime', dateObj);
},
setMinTime: function(input, dateObj){
jQuery(input).timepicker('option', 'minTime', dateObj);
},

// defaults for bootstrap datepicker; override when using other input widgets
parseDate: function(input){
return jQuery(input).datepicker('getDate');
},
updateDate: function(input, dateObj){
jQuery(input).datepicker('update', dateObj);
}
};

this.container = container;
this.settings = simpleExtend(this._defaults, options);

this.startDateInput = this.container.querySelector('.'+this.settings.startClass+'.'+this.settings.dateClass);
this.endDateInput = this.container.querySelector('.'+this.settings.endClass+'.'+this.settings.dateClass);
this.startTimeInput = this.container.querySelector('.'+this.settings.startClass+'.'+this.settings.timeClass);
this.endTimeInput = this.container.querySelector('.'+this.settings.endClass+'.'+this.settings.timeClass);

// init starts here
this._bindChangeHandler();
}

Datepair.prototype = {
constructor: Datepair,

_bindChangeHandler: function(){
// addEventListener doesn't work with synthetic "change" events
// fired by jQuery's trigger() functioin. If jQuery is present,
// use that for event binding
if (window.jQuery) {
jQuery(this.container).on('change.datepair', $.proxy(this.handleEvent, this));
} else {
this.container.addEventListener('change', this, false);
}
},

_unbindChangeHandler: function(){
if (window.jQuery) {
jQuery(this.container).off('change.datepair');
} else {
this.container.removeEventListener('change', this, false);
}
},

handleEvent: function(e){
// temporarily unbind the change handler to prevent triggering this
// if we update other inputs
this._unbindChangeHandler();

if (e.target.classList.contains(this.settings.dateClass)) {
if (e.target.value != '') {
this._dateChanged(e.target);
} else {
this.dateDelta = null;
}

} else if (e.target.classList.contains(this.settings.timeClass)) {
if (e.target.value != '') {
this._timeChanged(e.target);
} else {
this.timeDelta = null;
}
}

this._validateRanges();
this._updateEndMintime()
this._bindChangeHandler();
},

_dateChanged: function(target){
if (!this.startDateInput || !this.endDateInput) {
return
}

if (!this.startDateInput.value || !this.endDateInput.value) {
if (this.settings.defaultDateDelta !== null) {
if (this.startDateInput.value) {
var startDate = this.settings.parseDate(this.startDateInput);
var newEnd = new Date(startDate.getTime() + this.settings.defaultDateDelta * _ONE_DAY);
this.settings.updateDate(this.endDateInput, newEnd);

} else if (this.endDateInput.value) {
var endDate = this.settings.parseDate($endDateInput);
var newStart = new Date(endDate.getTime() - this.settings.defaultDateDelta * _ONE_DAY);
this.settings.updateDate(this.startDateInput, newStart);
}

this.dateDelta = this.settings.defaultDateDelta * _ONE_DAY;
} else {
this.dateDelta = null;
}

return;
}

var startDate = this.settings.parseDate(this.startDateInput);
var endDate = this.settings.parseDate(this.endDateInput);

if (target.classList.contains(this.settings.startClass)) {
var newEndDate = new Date(startDate.getTime() + this.dateDelta);
this.settings.updateDate(this.endDateInput, newEndDate);
} else if (target.classList.contains(this.settings.endClass)) {
if (endDate < startDate) {
this.dateDelta = 0;
this.settings.updateDate(this.startDateInput, endDate);
} else {
this.dateDelta = endDate.getTime() - startDate.getTime();
}
}
},

_timeChanged: function(target){
if (!this.startTimeInput || !this.endTimeInput) {
return
}

if (!this.startTimeInput.value || !this.endTimeInput.value) {
if (this.settings.defaultTimeDelta !== null) {
if (this.startTimeInput.value) {
var startTime = this.settings.parseTime(this.startTimeInput);
var newEnd = new Date(startTime.getTime() + this.settings.defaultTimeDelta);
this.settings.updateTime(this.endTimeInput, newEnd);
} else if (this.endTimeInput.value) {
var endTime = this.settings.parseTime(this.endTimeInput);
var newStart = new Date(endTime.getTime() - this.settings.defaultTimeDelta);
this.settings.updateTime(this.startTimeInput, newStart);
}

this.timeDelta = this.settings.defaultTimeDelta;
} else {
this.timeDelta = null;
}

return;
}

var startTime = this.settings.parseTime(this.startTimeInput);
var endTime = this.settings.parseTime(this.endTimeInput);

if (target.classList.contains(this.settings.startClass)) {
var newEndTime = new Date(startTime.getTime() + this.timeDelta);
this.settings.updateTime(this.endTimeInput, newEndTime);
endTime = this.settings.parseTime(this.endTimeInput);
}

if (this.endDateInput.value && this.dateDelta + this.timeDelta < _ONE_DAY && (endTime.getTime() - startTime.getTime()) * this.timeDelta < 0) {
var offset = (endTime < startTime) ? _ONE_DAY : -1 * _ONE_DAY;
var endDate = this.settings.parseDate(this.endDateInput);
this.settings.updateDate(this.endDateInput, new Date(endDate.getTime() + offset));
_dateChanged(this.endDateInput);
}

this.timeDelta = endTime.getTime() - startTime.getTime();
},

_updateEndMintime: function(){
if (typeof this.settings.setMinTime != 'function') return;

var startTime = null;
if (!this.dateDelta || this.dateDelta < _ONE_DAY || (this.timeDelta && this.dateDelta + this.timeDelta < _ONE_DAY)) {
startTime = this.settings.parseTime(this.startTimeInput);
}

this.settings.setMinTime(this.endTimeInput, startTime);
},

_validateRanges: function(){
if (this.startTimeInput && this.endTimeInput && this.timeDelta === null) {
triggerSimpleCustomEvent(this.container, 'rangeIncomplete');
return;
}

if (this.startDateInput && this.endDateInput && this.dateDelta === null) {
triggerSimpleCustomEvent(this.container, 'rangeIncomplete');
return;
}

if (this.dateDelta + this.timeDelta >= 0) {
triggerSimpleCustomEvent(this.container, 'rangeSelected');
} else {
triggerSimpleCustomEvent(this.container, 'rangeError');
}
}
}

window.Datepair = Datepair;

}(window, document));
7 changes: 7 additions & 0 deletions dist/datepair.min.js

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

Loading

0 comments on commit 2cc7618

Please sign in to comment.