calendar-tools
Advanced tools
Comparing version 0.1.6 to 0.1.7
@@ -114,3 +114,3 @@ var today = new Date() | ||
// creates Recurrence object | ||
var Recurrence = new caTools.Recurrence(events); | ||
var Recurrence = new caTools.recurrence(events); | ||
@@ -131,6 +131,3 @@ var instances = []; | ||
} | ||
}); | ||
}); | ||
@@ -0,1 +1,9 @@ | ||
0.1.7 / 2011-11-18 | ||
================== | ||
* add client-side builded file | ||
* add test rule to build client-side library using browserbuild | ||
* removing form lib/ working both-sides | ||
0.1.6 / 2011-11-11 | ||
@@ -2,0 +10,0 @@ ================== |
/*! | ||
* calendar-tools | ||
* Copyright(c) 2011 Damian Suarez <damian@learnboost.com> | ||
* MIT Licensed | ||
*/ | ||
* calendar-tools | ||
* Copyright(c) 2011 Damian Suarez <damian@learnboost.com> | ||
* MIT Licensed | ||
*/ | ||
(function (module, serverSide) { | ||
exports = module.exports; | ||
if (typeof module.exports == 'undefined') { | ||
module.exports = {}; | ||
} | ||
/** | ||
* Library version. | ||
*/ | ||
exports = module.exports; | ||
exports.version = '0.1.7'; | ||
/** | ||
* Library version. | ||
*/ | ||
/** | ||
* Expose recurrence | ||
*/ | ||
exports.version = '0.1.6'; | ||
exports.recurrence = require('./recurrence'); | ||
/** | ||
* Expose recurrence | ||
*/ | ||
/** | ||
* Expose seed | ||
*/ | ||
exports.recurrence = require('./recurrence'); | ||
exports.seed = require('./seed'); | ||
/** | ||
* Expose seed | ||
*/ | ||
/** | ||
* Expose util | ||
*/ | ||
exports.seed = require('./seed'); | ||
exports.util = require('./util'); | ||
/** | ||
* Expose util | ||
*/ | ||
exports.util = require('./util'); | ||
// client-side: add caTools global var | ||
if (!serverSide) { | ||
if (typeof window.caTools == 'undefined') | ||
window.caTools = {}; | ||
for (var k in exports) | ||
window.caTools[k] = exports[k]; | ||
} | ||
})(typeof module != 'undefined' ? module : {}, typeof window != 'object'); |
/*! | ||
* Instance | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
* Instance | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
/** | ||
* add util module | ||
*/ | ||
// by-side behavour | ||
(function(module, serverSide) { | ||
if (typeof module.exports == 'undefined') | ||
module.exports = {}; | ||
var util = require('./util'); | ||
/** | ||
* add util module | ||
*/ | ||
/** | ||
* alias | ||
*/ | ||
var util = serverSide ? require('./util') : window.caTools.Util | ||
var _date = util.date; | ||
/** | ||
* alias | ||
*/ | ||
/** | ||
* exports Instance Class | ||
*/ | ||
var _date = util.date; | ||
var modInstance = module.exports = function (Seed, options) { | ||
return new Instance(Seed, options); | ||
} | ||
/** | ||
* exports Instance Class | ||
*/ | ||
/** | ||
* Instance class. Creates a instance of seed event | ||
*/ | ||
var modInstance = module.exports = function (Seed, options) { | ||
return new Instance(Seed, options); | ||
} | ||
function Instance (Seed, dateReference) { | ||
this._seed = Seed; | ||
this._create(dateReference); | ||
} | ||
/** | ||
* Instance class. Creates a instance of seed event | ||
*/ | ||
// alias Instance prototype | ||
var pptInst = Instance.prototype; | ||
function Instance (Seed, dateReference) { | ||
this._seed = Seed; | ||
this._create(dateReference); | ||
} | ||
/** | ||
* creates an instance event | ||
*/ | ||
// alias Instance prototype | ||
var pptInst = Instance.prototype; | ||
pptInst._create = function (dateReference) { | ||
var clone = this.clone() | ||
, diff = _date.getDiff(this._seed.ev.end, this._seed.ev.start); | ||
/** | ||
* creates an instance event | ||
*/ | ||
// set cloned start date | ||
clone.start = new Date( | ||
dateReference.getFullYear() | ||
, dateReference.getMonth() | ||
, dateReference.getDate() | ||
, this._seed.ev.start.getHours() | ||
, this._seed.ev.start.getMinutes() | ||
, this._seed.ev.start.getSeconds() | ||
, this._seed.ev.start.getMilliseconds() | ||
); | ||
pptInst._create = function (dateReference) { | ||
var clone = this.clone() | ||
, diff = _date.getDiff(this._seed.ev.end, this._seed.ev.start); | ||
// set cloned end date | ||
clone.end = new Date(+clone.start + diff); | ||
_date.applyTZCorrection(clone.end, clone.start); | ||
// set cloned start date | ||
clone.start = new Date( | ||
dateReference.getFullYear() | ||
, dateReference.getMonth() | ||
, dateReference.getDate() | ||
, this._seed.ev.start.getHours() | ||
, this._seed.ev.start.getMinutes() | ||
, this._seed.ev.start.getSeconds() | ||
, this._seed.ev.start.getMilliseconds() | ||
); | ||
// set cloned instances as Instance Object properties | ||
for (var k in clone) | ||
this[k] = clone[k]; | ||
// set cloned end date | ||
clone.end = new Date(+clone.start + diff); | ||
_date.applyTZCorrection(clone.end, clone.start); | ||
return clone; | ||
} | ||
// set cloned instances as Instance Object properties | ||
for (var k in clone) | ||
this[k] = clone[k]; | ||
/** | ||
* clone an seed event | ||
*/ | ||
return clone; | ||
} | ||
pptInst.clone = function () { | ||
var newInstance = JSON.parse(JSON.stringify(this._seed.ev)); | ||
/** | ||
* clone an seed event | ||
*/ | ||
newInstance.start = new Date(newInstance.start); | ||
newInstance.end = new Date(newInstance.end); | ||
pptInst.clone = function () { | ||
var newInstance = JSON.parse(JSON.stringify(this._seed.ev)); | ||
if (newInstance.stop) | ||
newInstance.stop = _date.parseISO8601(newInstance.stop); | ||
newInstance.start = new Date(newInstance.start); | ||
newInstance.end = new Date(newInstance.end); | ||
if (newInstance.stop) | ||
newInstance.stop = _date.parseISO8601(newInstance.stop); | ||
// on date generation | ||
if (newInstance.recurrence) { | ||
var endBy = newInstance.recurrence['end-by']; | ||
if (endBy && endBy.on) | ||
newInstance.recurrence['end-by'].on = new Date(endBy.on); | ||
} | ||
return newInstance; | ||
}; | ||
/** | ||
* get the instance number | ||
*/ | ||
pptInst.getNumber = function () { | ||
return this.n; | ||
// on date generation | ||
if (newInstance.recurrence) { | ||
var endBy = newInstance.recurrence['end-by']; | ||
if (endBy && endBy.on) | ||
newInstance.recurrence['end-by'].on = new Date(endBy.on); | ||
} | ||
return newInstance; | ||
}; | ||
/** | ||
* get if is the last instance into series | ||
*/ | ||
/** | ||
* get the instance number | ||
*/ | ||
pptInst.isLast = function () { | ||
var c = this.getSeed()._getCountdown(); | ||
return this.getNumber() === (c - 1); | ||
} | ||
pptInst.getNumber = function () { | ||
return this.n; | ||
} | ||
/** | ||
* get the previous instance into series | ||
*/ | ||
pptInst.getPrev = function () { | ||
return this._prevInst; | ||
} | ||
/** | ||
* get if is the last instance into series | ||
*/ | ||
/** | ||
* get the seed event | ||
*/ | ||
pptInst.isLast = function () { | ||
var c = this.getSeed()._getCountdown(); | ||
return this.getNumber() === (c - 1); | ||
} | ||
pptInst.getSeed = function () { | ||
return this._seed; | ||
} | ||
/** | ||
* get the previous instance into series | ||
*/ | ||
// client-side: add caTools global var | ||
if (!serverSide) { | ||
if (typeof window.caTools == 'undefined') | ||
window.caTools = {}; | ||
pptInst.getPrev = function () { | ||
return this._prevInst; | ||
} | ||
window.caTools.Instance = modInstance; | ||
} | ||
/** | ||
* get the seed event | ||
*/ | ||
})(typeof module != 'undefined' ? module : {}, typeof window != 'object'); | ||
pptInst.getSeed = function () { | ||
return this._seed; | ||
} |
/*! | ||
* recurrence | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
* recurrence | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
/** | ||
* modeule dependencies | ||
*/ | ||
var Seed = require('./seed'); | ||
// by-side behavour | ||
(function(module, serverSide) { | ||
/** | ||
* exports recurrence Class | ||
*/ | ||
if (typeof module.exports == 'undefined') | ||
module.exports = {}; | ||
var modRecurrence = module.exports = function (evs, options) { | ||
return new Recurrence(evs, options); | ||
} | ||
/** | ||
* modeule dependencies | ||
*/ | ||
var Seed = serverSide ? require('./seed') : window.caTools.Seed; | ||
/** | ||
* Initialize a new 'Recurrence' object with the given 'ev' | ||
* | ||
* @param {Object|Array} evs: object event or an array events collection | ||
* @param {Object} options: { | ||
* period: { | ||
* start: {Date} - period start date | ||
* , end: {Date} - period end date | ||
* } | ||
* , addNoRec: {Boolean} - add no-recurrence events | ||
* , systemTZCorrection: {Boolean} - apply system timezone correction | ||
* , offsetCorrection: {Number} - apply offset correction (minutes) | ||
* } | ||
/** | ||
* exports recurrence Class | ||
*/ | ||
* return {Array} instances series | ||
*/ | ||
var modRecurrence = module.exports = function (evs, options) { | ||
return new Recurrence(evs, options); | ||
} | ||
function Recurrence (evs, options) { | ||
// add default options | ||
var start = new Date() | ||
this.options = { | ||
start: start | ||
, end: new Date(+start + 1000*60*6024) | ||
, addNoRec: true | ||
, systemTZCorrection: false | ||
, offsetCorrection: 0 | ||
}; | ||
/** | ||
* Initialize a new 'Recurrence' object with the given 'ev' | ||
* | ||
* @param {Object|Array} evs: object event or an array events collection | ||
* @param {Object} options: { | ||
* period: { | ||
* start: {Date} - period start date | ||
* , end: {Date} - period end date | ||
* } | ||
* , addNoRec: {Boolean} - add no-recurrence events | ||
* , systemTZCorrection: {Boolean} - apply system timezone correction | ||
* , offsetCorrection: {Number} - apply offset correction (minutes) | ||
* } | ||
// mix options | ||
for (var k in options) | ||
this.options[k] = options[k]; | ||
* return {Array} instances series | ||
*/ | ||
// store events | ||
evs = evs instanceof Array ? evs : [evs]; | ||
this.events = evs; | ||
function Recurrence (evs, options) { | ||
// add default options | ||
var start = new Date() | ||
this.options = { | ||
start: start | ||
, end: new Date(+start + 1000*60*6024) | ||
, addNoRec: true | ||
, systemTZCorrection: false | ||
, offsetCorrection: 0 | ||
}; | ||
// set period | ||
this.setPeriod(); | ||
// mix options | ||
for (var k in options) | ||
this.options[k] = options[k]; | ||
// planting seeds | ||
this.seeds = []; | ||
this.plantingSeeds(); | ||
} | ||
// store events | ||
evs = evs instanceof Array ? evs : [evs]; | ||
this.events = evs; | ||
// proto alias | ||
var _pttRec = Recurrence.prototype; | ||
// set period | ||
this.setPeriod(); | ||
/** | ||
* setPeriod() method. | ||
*/ | ||
// planting seeds | ||
this.seeds = []; | ||
this.plantingSeeds(); | ||
} | ||
_pttRec.setPeriod = function (start, end) { | ||
start = start || this.options.start || new Date(); | ||
end = end || this.options.end; | ||
// proto alias | ||
var _pttRec = Recurrence.prototype; | ||
/** | ||
* setPeriod() method. | ||
*/ | ||
_pttRec.setPeriod = function (start, end) { | ||
start = start || this.options.start || new Date(); | ||
end = end || this.options.end; | ||
// set period | ||
if (!end) { | ||
end = new Date(+start); | ||
end.setDate(start.getDate() + 1); | ||
} | ||
var p = this.period = { | ||
start: typeof start == 'string' ? new Date(start) : start | ||
, end: typeof end == 'string' ? new Date(end) : end | ||
}; | ||
return p; | ||
// set period | ||
if (!end) { | ||
end = new Date(+start); | ||
end.setDate(start.getDate() + 1); | ||
} | ||
/** | ||
* planting seeds. That is register all events crating 'seed' objects | ||
*/ | ||
var p = this.period = { | ||
start: typeof start == 'string' ? new Date(start) : start | ||
, end: typeof end == 'string' ? new Date(end) : end | ||
}; | ||
_pttRec.plantingSeeds = function () { | ||
for (var s = 0; s < this.events.length; s++) | ||
this.seeds.push(new Seed(this.events[s], this, this.options)); | ||
} | ||
return p; | ||
} | ||
/** | ||
* return seeed events | ||
*/ | ||
/** | ||
* planting seeds. That is register all events crating 'seed' objects | ||
*/ | ||
_pttRec.getSeeds = function () { | ||
return this.seeds; | ||
} | ||
_pttRec.plantingSeeds = function () { | ||
for (var s = 0; s < this.events.length; s++) | ||
this.seeds.push(new Seed(this.events[s], this, this.options)); | ||
} | ||
/** | ||
* getInstances() | ||
* | ||
* return {Array} all instances of all seed events | ||
*/ | ||
/** | ||
* return seeed events | ||
*/ | ||
_pttRec.getInstances = function (start, end) { | ||
var allInstances = []; | ||
_pttRec.getSeeds = function () { | ||
return this.seeds; | ||
} | ||
for (var i = 0; i < this.seeds.length; i++) { | ||
var seed = this.seeds[i]; | ||
allInstances = allInstances.concat(seed.getInstances(start, end)); | ||
}; | ||
/** | ||
* getInstances() | ||
* | ||
* return {Array} all instances of all seed events | ||
*/ | ||
return allInstances; | ||
} | ||
_pttRec.getInstances = function (start, end) { | ||
var allInstances = []; | ||
// client-side: add caTools global var | ||
if (!serverSide) { | ||
if (typeof window.caTools == 'undefined') | ||
window.caTools = {}; | ||
for (var i = 0; i < this.seeds.length; i++) { | ||
var seed = this.seeds[i]; | ||
allInstances = allInstances.concat(seed.getInstances(start, end)); | ||
}; | ||
window.caTools.Recurrence = modRecurrence; | ||
} | ||
})(typeof module != 'undefined' ? module : {}, typeof window != 'object'); | ||
return allInstances; | ||
} |
/*! | ||
* calen | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
* calen | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
/** | ||
* Module dependecies | ||
*/ | ||
// by-side behavour | ||
(function(module) { | ||
var Util = require('./util'); | ||
/** | ||
* Module dependecies | ||
*/ | ||
/** | ||
* Alias | ||
*/ | ||
var Util = require('./util'); | ||
var _str = Util.string | ||
, _date = Util.date; | ||
/** | ||
* Alias | ||
*/ | ||
/** | ||
* freqquency names map | ||
*/ | ||
var _str = Util.string | ||
, _date = Util.date; | ||
var freqNamesMap = { | ||
YEARLY: 'year' | ||
, MONTHLY: 'month' | ||
, WEEKLY: 'week' | ||
, DAILY: 'day' | ||
}; | ||
/** | ||
* freqquency names map | ||
*/ | ||
/** | ||
* days map from RFC2445 protocol to recurrence structure | ||
*/ | ||
var freqNamesMap = { | ||
YEARLY: 'year' | ||
, MONTHLY: 'month' | ||
, WEEKLY: 'week' | ||
, DAILY: 'day' | ||
}; | ||
const daysMapRFC2445toRec = { | ||
SU: 'su' | ||
, MO: 'm' | ||
, TU: 't' | ||
, WE: 'w' | ||
, TH: 'th' | ||
, FR: 'f' | ||
, SA: 'sa' | ||
} | ||
/** | ||
* days map from RFC2445 protocol to recurrence structure | ||
*/ | ||
/** | ||
* days map from recurrence structure to RFC2445 protocol | ||
*/ | ||
const daysMapRFC2445toRec = { | ||
SU: 'su' | ||
, MO: 'm' | ||
, TU: 't' | ||
, WE: 'w' | ||
, TH: 'th' | ||
, FR: 'f' | ||
, SA: 'sa' | ||
} | ||
const daysMapRecToRFC2445 = { | ||
su: 'SU' | ||
, m: 'MO' | ||
, t: 'TU' | ||
, w: 'WE' | ||
, th: 'TH' | ||
, f: 'FR' | ||
, sa: 'SA' | ||
} | ||
/** | ||
* days map from recurrence structure to RFC2445 protocol | ||
*/ | ||
/** | ||
* days names | ||
*/ | ||
const daysMapRecToRFC2445 = { | ||
su: 'SU' | ||
, m: 'MO' | ||
, t: 'TU' | ||
, w: 'WE' | ||
, th: 'TH' | ||
, f: 'FR' | ||
, sa: 'SA' | ||
} | ||
const dayNames = ['su', 'm', 't', 'w', 'th', 'f', 'sa']; | ||
/** | ||
* days names | ||
*/ | ||
/** | ||
* RFC2445 usefull functions | ||
*/ | ||
const dayNames = ['su', 'm', 't', 'w', 'th', 'f', 'sa']; | ||
var RFC2445 = module.exports = {}; | ||
/** | ||
* RFC2445 usefull functions | ||
*/ | ||
/********************** | ||
* generate functions * | ||
**********************/ | ||
var RFC2445 = module.exports = {}; | ||
/** | ||
* genRecurrenceString | ||
* generates a RFC2445 recurrence string passing an Event Object | ||
* | ||
* @param {Object} ev: Event Object | ||
* @param {String} tz: timezone location | ||
* | ||
* return {String} RFC2445 recurrence string | ||
*/ | ||
/********************** | ||
* generate functions * | ||
**********************/ | ||
RFC2445.genRecurrenceString = function (ev, tz) { | ||
if (!ev.frequency) return ''; | ||
/** | ||
* genRecurrenceString | ||
* generates a RFC2445 recurrence string passing an Event Object | ||
* | ||
* @param {Object} ev: Event Object | ||
* @param {String} tz: timezone location | ||
* | ||
* return {String} RFC2445 recurrence string | ||
*/ | ||
tz = tz || ev.location; | ||
RFC2445.genRecurrenceString = function (ev, tz) { | ||
if (!ev.frequency) return ''; | ||
// period: DTSTART, DTEND | ||
var rules = [ | ||
'DTSTART;' + (ev.allDay | ||
? _str.value(ev.start) | ||
: _str.dateTZID(ev.start, tz)) | ||
, 'DTEND;' + (ev.allDay | ||
? _str.value(ev.end) | ||
: _str.dateTZID(ev.end, tz)) | ||
]; | ||
tz = tz || ev.location; | ||
// RRULE - frequency value | ||
var rrule = '' | ||
, steps = ['freq', 'repeat', 'end-by', 'interval'] | ||
, endBy = '' | ||
, interval = ''; | ||
// period: DTSTART, DTEND | ||
var rules = [ | ||
'DTSTART;' + (ev.allDay | ||
? _str.value(ev.start) | ||
: _str.dateTZID(ev.start, tz)) | ||
, 'DTEND;' + (ev.allDay | ||
? _str.value(ev.end) | ||
: _str.dateTZID(ev.end, tz)) | ||
]; | ||
// end-by type | ||
// RRULE - frequency value | ||
var rrule = '' | ||
, steps = ['freq', 'repeat', 'end-by', 'interval'] | ||
, endBy = '' | ||
, interval = ''; | ||
// COUNT | ||
if (ev.recurrence['end-by'].type == 'after') | ||
endBy = ';COUNT=' + ev.recurrence['end-by'].after; | ||
// ON | ||
if (ev.recurrence['end-by'].type == 'on') | ||
endBy = ';UNTIL=' + _str.value(ev.recurrence['end-by'].on, true); | ||
// end-by type | ||
// INTERVAL | ||
if (ev.recurrence.every != 1) | ||
interval = ';INTERVAL=' + ev.recurrence.every; | ||
// COUNT | ||
if (ev.recurrence['end-by'].type == 'after') | ||
endBy = ';COUNT=' + ev.recurrence['end-by'].after; | ||
// ON | ||
if (ev.recurrence['end-by'].type == 'on') | ||
endBy = ';UNTIL=' + _str.value(ev.recurrence['end-by'].on, true); | ||
for (var st = 0; st < steps.length; st++) { | ||
if (st == 0 || st == 2) { | ||
switch (ev.frequency) { | ||
case 'year': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=YEARLY' | ||
: ''; | ||
break; | ||
// INTERVAL | ||
if (ev.recurrence.every != 1) | ||
interval = ';INTERVAL=' + ev.recurrence.every; | ||
case 'month': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=MONTHLY' | ||
: (st == 2 | ||
? (ev.recurrence['repeat-on'].mode == 'day-of-month' | ||
? ';BYMONTHDAY=1' | ||
: ';BYDAY=1' | ||
+ daysMapRecToRFC2445[dayNames[ev.start.getDay()]]) | ||
: ''); | ||
break; | ||
for (var st = 0; st < steps.length; st++) { | ||
if (st == 0 || st == 2) { | ||
switch (ev.frequency) { | ||
case 'year': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=YEARLY' | ||
: ''; | ||
break; | ||
case 'week': | ||
var days = ''; | ||
for (var k in ev.recurrence['repeat-on']) | ||
days += daysMapRecToRFC2445[k] + ',' | ||
case 'month': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=MONTHLY' | ||
: (st == 2 | ||
? (ev.recurrence['repeat-on'].mode == 'day-of-month' | ||
? ';BYMONTHDAY=1' | ||
: ';BYDAY=1' | ||
+ daysMapRecToRFC2445[dayNames[ev.start.getDay()]]) | ||
: ''); | ||
break; | ||
days = days.substring(0, days.length - 1); | ||
case 'week': | ||
var days = ''; | ||
for (var k in ev.recurrence['repeat-on']) | ||
days += daysMapRecToRFC2445[k] + ',' | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=WEEKLY;BYDAY=' + days | ||
: ''; | ||
break; | ||
days = days.substring(0, days.length - 1); | ||
case 'day': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=DAILY' | ||
: ''; | ||
break; | ||
}; | ||
} | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=WEEKLY;BYDAY=' + days | ||
: ''; | ||
break; | ||
// add end-by | ||
else if (st == 1) | ||
rrule += endBy; | ||
case 'day': | ||
rrule += st == 0 | ||
? 'RRULE:FREQ=DAILY' | ||
: ''; | ||
break; | ||
}; | ||
} | ||
// add end-by | ||
else if (st == 3) | ||
rrule += interval; | ||
// add end-by | ||
else if (st == 1) | ||
rrule += endBy; | ||
}; | ||
// add end-by | ||
else if (st == 3) | ||
rrule += interval; | ||
rules.push(rrule); | ||
}; | ||
return rules.join("\r\n"); | ||
} | ||
rules.push(rrule); | ||
/********************* | ||
* getting functions * | ||
*********************/ | ||
return rules.join("\r\n"); | ||
} | ||
/** | ||
* getRecurrenceObj() method. | ||
* return a recurrence object of LearnBoost event passing RFC2445 string | ||
* | ||
* @param {string} str: RFC2445 recurrence string | ||
* return {Object} recurrence LearnBoost object | ||
*/ | ||
/********************* | ||
* getting functions * | ||
*********************/ | ||
RFC2445.getRecurrenceObj = function (str) { | ||
// debug: RFC2445 \x1B[0;33m%s\x1B[0m string to recurrence object, str | ||
var recRule = str.match(/RRULE([^ ]+)/) | ||
, recObj = { | ||
every: 1 | ||
, 'end-by': {} | ||
, exceptions: [] | ||
, 'repeat-on': {} | ||
} | ||
, _freq = ''; | ||
/** | ||
* getRecurrenceObj() method. | ||
* return a recurrence object of LearnBoost event passing RFC2445 string | ||
* | ||
* @param {string} str: RFC2445 recurrence string | ||
* return {Object} recurrence LearnBoost object | ||
*/ | ||
recRule = recRule.length ? recRule[0] : null; | ||
RFC2445.getRecurrenceObj = function (str) { | ||
// debug: RFC2445 \x1B[0;33m%s\x1B[0m string to recurrence object, str | ||
var recRule = str.match(/RRULE([^ ]+)/) | ||
, recObj = { | ||
every: 1 | ||
, 'end-by': {} | ||
, exceptions: [] | ||
, 'repeat-on': {} | ||
} | ||
, _freq = ''; | ||
if (!recRule) return null; | ||
recRule = recRule.length ? recRule[0] : null; | ||
// debug: recurrence rule \x1B[0;33m%s\x1B[0m, recRule | ||
if (!recRule) return null; | ||
var recPrpsRule = recRule.split(';'); | ||
// debug: recurrence rule \x1B[0;33m%s\x1B[0m, recRule | ||
for (var k = 0; k < recPrpsRule.length; k++) { | ||
var prp = recPrpsRule[k].split('='); | ||
// debug: recurrence property [%s]: \x1B[0;33m%s: %j\x1B[0m, k, prp[0], prp[1] | ||
var recPrpsRule = recRule.split(';'); | ||
// recurrence type | ||
if (prp[0] == 'RRULE:FREQ') { | ||
_freq = prp[1]; | ||
} | ||
for (var k = 0; k < recPrpsRule.length; k++) { | ||
var prp = recPrpsRule[k].split('='); | ||
// debug: recurrence property [%s]: \x1B[0;33m%s: %j\x1B[0m, k, prp[0], prp[1] | ||
// INTERVAL/repeat | ||
if (prp[0] == 'INTERVAL') { | ||
recObj.every = prp[1]; | ||
} | ||
// recurrence type | ||
if (prp[0] == 'RRULE:FREQ') { | ||
_freq = prp[1]; | ||
} | ||
// end-by properties | ||
// AFTER mode | ||
else if (prp[0] == 'COUNT') { | ||
recObj['end-by'].type = 'after'; | ||
recObj['end-by'].after = prp[1]; | ||
} | ||
// INTERVAL/repeat | ||
if (prp[0] == 'INTERVAL') { | ||
recObj.every = prp[1]; | ||
} | ||
// UNTIL/on mode | ||
else if (prp[0] == 'UNTIL') { | ||
recObj['end-by'].type = 'on'; | ||
var data = _date.parseFromWeirdISOFormat(prp[1]); | ||
recObj['end-by'].on = new Date(data); | ||
} | ||
// end-by properties | ||
// AFTER mode | ||
else if (prp[0] == 'COUNT') { | ||
recObj['end-by'].type = 'after'; | ||
recObj['end-by'].after = prp[1]; | ||
// BYDAY/repeat-on. Used for: | ||
// - weekly mode | ||
// - monthly mode - day on week | ||
else if (prp[0] == 'BYDAY') { | ||
if (_freq == 'WEEKLY') { | ||
var days = prp[1].split(','); | ||
for (var k = 0; k < days.length; k++) { | ||
var key = daysMapRFC2445toRec[days[k]]; | ||
recObj['repeat-on'][key] = 'on'; | ||
}; | ||
} | ||
// UNTIL/on mode | ||
else if (prp[0] == 'UNTIL') { | ||
recObj['end-by'].type = 'on'; | ||
var data = _date.parseFromWeirdISOFormat(prp[1]); | ||
recObj['end-by'].on = new Date(data); | ||
else if (_freq == 'MONTHLY') { | ||
// for monthly trecurrence type simply defines mode | ||
recObj['repeat-on'].mode = 'day-of-week'; | ||
} | ||
} | ||
// BYDAY/repeat-on. Used for: | ||
// - weekly mode | ||
// - monthly mode - day on week | ||
else if (prp[0] == 'BYDAY') { | ||
// BYMONTHDAY/repeat-on. Used for: | ||
// - weekly mode | ||
else if (prp[0] == 'BYMONTHDAY' && prp[1] == 1) | ||
recObj['repeat-on'].mode = 'day-of-month'; | ||
if (_freq == 'WEEKLY') { | ||
var days = prp[1].split(','); | ||
for (var k = 0; k < days.length; k++) { | ||
var key = daysMapRFC2445toRec[days[k]]; | ||
recObj['repeat-on'][key] = 'on'; | ||
}; | ||
} | ||
else if (_freq == 'MONTHLY') { | ||
// for monthly trecurrence type simply defines mode | ||
recObj['repeat-on'].mode = 'day-of-week'; | ||
} | ||
} | ||
// BYMONTHDAY/repeat-on. Used for: | ||
// - weekly mode | ||
else if (prp[0] == 'BYMONTHDAY' && prp[1] == 1) | ||
recObj['repeat-on'].mode = 'day-of-month'; | ||
}; | ||
// setting default options | ||
// end-by type | ||
recObj['end-by'].type = recObj['end-by'].type || 'never'; | ||
return recObj; | ||
}; | ||
/** | ||
* getFrequency | ||
* retrieve frequency property from google RFC2445 recurrence string | ||
* | ||
* @param {string} str | ||
* @param {Object} frequency names map | ||
* { | ||
* YEARLY: 'year' | ||
* , MONTH: 'month' | ||
* , WEEKLY: 'week' | ||
* , DAILY': 'day' | ||
* } | ||
*/ | ||
// setting default options | ||
// end-by type | ||
recObj['end-by'].type = recObj['end-by'].type || 'never'; | ||
RFC2445.getFrequency = function (str, namesMap) { | ||
// debug: get frequency property from RFC2445 \x1B[0;33m%s\x1B[0m, str | ||
// frequency names map | ||
namesMap = namesMap || freqNamesMap; | ||
var frequency = str.match(/FREQ=([A-Z]+)/); | ||
return recObj; | ||
}; | ||
if (frequency) | ||
return namesMap[frequency[1]]; | ||
return null; | ||
}; | ||
/** | ||
* getFrequency | ||
* retrieve frequency property from google RFC2445 recurrence string | ||
* | ||
* @param {string} str | ||
* @param {Object} frequency names map | ||
* { | ||
* YEARLY: 'year' | ||
* , MONTH: 'month' | ||
* , WEEKLY: 'week' | ||
* , DAILY': 'day' | ||
* } | ||
*/ | ||
/** | ||
* retirve all-day property from RFC2445 recurrence string | ||
*/ | ||
RFC2445.getFrequency = function (str, namesMap) { | ||
// debug: get frequency property from RFC2445 \x1B[0;33m%s\x1B[0m, str | ||
// frequency names map | ||
namesMap = namesMap || freqNamesMap; | ||
var frequency = str.match(/FREQ=([A-Z]+)/); | ||
RFC2445.getAllday = function (str) { | ||
// debug: get all-day property from RFC2445 \x1B[0;33m%s\x1B[0m, str | ||
// deduces 'all-day' property through the DTSTART format property | ||
var dtstart = str.match(/(^DTSTART;([^ ]+))(:\w+)(T)/); | ||
if (frequency) | ||
return namesMap[frequency[1]]; | ||
return null; | ||
}; | ||
return dtstart ? false : true; | ||
}; | ||
/** | ||
* retirve all-day property from RFC2445 recurrence string | ||
*/ | ||
// executes (client side) or exports the module (server side) | ||
if (typeof window == 'object') | ||
$.fullCalendar.utils = module.exports; | ||
RFC2445.getAllday = function (str) { | ||
// debug: get all-day property from RFC2445 \x1B[0;33m%s\x1B[0m, str | ||
// deduces 'all-day' property through the DTSTART format property | ||
var dtstart = str.match(/(^DTSTART;([^ ]+))(:\w+)(T)/); | ||
})(typeof module != 'undefined' ? module : {}); | ||
return dtstart ? false : true; | ||
}; |
950
lib/seed.js
/*! | ||
* seed | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
* seed | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
/** | ||
* add util module | ||
*/ | ||
// by-side behavour | ||
(function(module, serverSide) { | ||
if (typeof module.exports == 'undefined') | ||
module.exports = {}; | ||
var util = require('./util') | ||
, Instance = require('./instance'); | ||
/** | ||
* add util module | ||
*/ | ||
/** | ||
* alias | ||
*/ | ||
var util = serverSide ? require('./util') : window.caTools.Util | ||
, Instance = serverSide ? require('./instance') : window.caTools.Instance; | ||
var _date = util.date | ||
, _c = _date.const | ||
, clearTime = _date.clearTime | ||
/** | ||
* alias | ||
*/ | ||
/** | ||
* exports Seed Class | ||
*/ | ||
var _date = util.date | ||
, _c = _date.const | ||
, clearTime = _date.clearTime | ||
var modSeed = module.exports = function (ev, parent, options) { | ||
return new Seed(ev, parent, options); | ||
} | ||
/** | ||
* exports Seed Class | ||
*/ | ||
/** | ||
* Seed class | ||
*/ | ||
var modSeed = module.exports = function (ev, parent, options) { | ||
return new Seed(ev, parent, options); | ||
} | ||
function Seed (ev) { | ||
if (!ev) | ||
throw new Error ('Seed: need necessary an event to generate instances'); | ||
/** | ||
* Seed class | ||
*/ | ||
var args = arguments; | ||
// Seed is called for Recurrence? | ||
var calledByRec = args[1] && args[1].events; | ||
function Seed (ev) { | ||
if (!ev) | ||
throw new Error ('Seed: need necessary an event to generate instances'); | ||
if (!calledByRec) | ||
this.parent = { | ||
options: {} | ||
} | ||
else | ||
this.parent = args[1]; | ||
var args = arguments; | ||
// Seed is called for Recurrence? | ||
var calledByRec = args[1] && args[1].events; | ||
// options | ||
var options = calledByRec ? args[2] : args[1]; | ||
this.options = { | ||
addNoRec: false | ||
, offsetCorrection: 0 | ||
}; | ||
if (!calledByRec) | ||
this.parent = { | ||
options: {} | ||
} | ||
else | ||
this.parent = args[1]; | ||
// mix options | ||
for (var k in options) | ||
this.options[k] = options[k]; | ||
// options | ||
var options = calledByRec ? args[2] : args[1]; | ||
this.options = { | ||
addNoRec: false | ||
, offsetCorrection: 0 | ||
}; | ||
// set event like a object property | ||
this.ev = ev; | ||
// mix options | ||
for (var k in options) | ||
this.options[k] = options[k]; | ||
// normalize seed | ||
this.normalize(); | ||
// set event like a object property | ||
this.ev = ev; | ||
if (this.options.start) | ||
this.setPeriod(); | ||
} | ||
// normalize seed | ||
this.normalize(); | ||
// alias Instance prototype | ||
var pptSeed = Seed.prototype; | ||
if (this.options.start) | ||
this.setPeriod(); | ||
} | ||
/** | ||
* setPeriod() | ||
* set period limiting the series generation | ||
* | ||
* @param {Date} start: period start date | ||
* @Param {Date} end: period end date | ||
*/ | ||
// alias Instance prototype | ||
var pptSeed = Seed.prototype; | ||
pptSeed.setPeriod = function (start, end) { | ||
start = start || this.options.start || this.parent.period.start || new Date(); | ||
end = end || this.options.end || this.parent.period.end; | ||
/** | ||
* setPeriod() | ||
* set period limiting the series generation | ||
* | ||
* @param {Date} start: period start date | ||
* @Param {Date} end: period end date | ||
*/ | ||
// set period | ||
if (!end) { | ||
end = new Date(+start); | ||
end.setDate(start.getDate() + 1); | ||
} | ||
pptSeed.setPeriod = function (start, end) { | ||
start = start || this.options.start || this.parent.period.start || new Date(); | ||
end = end || this.options.end || this.parent.period.end; | ||
var p = this.period = { | ||
start: typeof start == 'string' ? new Date(start) : start | ||
, end: typeof end == 'string' ? new Date(end) : end | ||
}; | ||
// set period | ||
if (!end) { | ||
end = new Date(+start); | ||
end.setDate(start.getDate() + 1); | ||
} | ||
return p; | ||
} | ||
var p = this.period = { | ||
start: typeof start == 'string' ? new Date(start) : start | ||
, end: typeof end == 'string' ? new Date(end) : end | ||
}; | ||
/** | ||
* normalize() | ||
* normalize some event properties | ||
*/ | ||
return p; | ||
pptSeed.normalize = function () { | ||
// date tz correction. tz in minutes | ||
function tzCorrection(date, tz) { | ||
if(!date) return date; | ||
date.setMinutes(date.getMinutes() - tz); | ||
return date; | ||
} | ||
/** | ||
* normalize() | ||
* normalize some event properties | ||
*/ | ||
// converts string to date object if is neccesary | ||
if (typeof this.ev.start == 'string') | ||
this.ev.start = new Date(this.ev.start); | ||
pptSeed.normalize = function () { | ||
// date tz correction. tz in minutes | ||
function tzCorrection(date, tz) { | ||
if(!date) return date; | ||
date.setMinutes(date.getMinutes() - tz); | ||
return date; | ||
} | ||
if (typeof this.ev.end == 'string') | ||
this.ev.end = new Date(this.ev.end); | ||
// converts string to date object if is neccesary | ||
if (typeof this.ev.start == 'string') | ||
this.ev.start = new Date(this.ev.start); | ||
if (typeof this.ev.stop == 'string') | ||
this.ev.stop = new Date(this.ev.stop); | ||
if (typeof this.ev.end == 'string') | ||
this.ev.end = new Date(this.ev.end); | ||
// timezone system correction | ||
// - apply offsetCorrection + systemTZCorrection | ||
var offset = this.options.offsetCorrection + ( | ||
this.options.systemTZCorrection | ||
? this.ev.start.getTimezoneOffset() | ||
: 0 | ||
); | ||
if (typeof this.ev.stop == 'string') | ||
this.ev.stop = new Date(this.ev.stop); | ||
// timezone/offset correction | ||
tzCorrection(this.ev.start, offset); | ||
tzCorrection(this.ev.end, offset); | ||
tzCorrection(this.ev.stop, offset); | ||
// timezone system correction | ||
// - apply offsetCorrection + systemTZCorrection | ||
var offset = this.options.offsetCorrection + ( | ||
this.options.systemTZCorrection | ||
? this.ev.start.getTimezoneOffset() | ||
: 0 | ||
); | ||
// weekly mode | ||
if (this.ev.frequency == 'week') { | ||
// build jumping vector | ||
this.setJumpingVector(); | ||
// timezone/offset correction | ||
tzCorrection(this.ev.start, offset); | ||
tzCorrection(this.ev.end, offset); | ||
tzCorrection(this.ev.stop, offset); | ||
// avoid falling into the void. start/end date offset correction | ||
if (!this.jumpingVector[this.ev.start.getDay()]) { | ||
var jmp = this.jumpingVector | ||
, jl = jmp.length; | ||
// weekly mode | ||
if (this.ev.frequency == 'week') { | ||
// build jumping vector | ||
this.setJumpingVector(); | ||
for (var i = 0; i < jl; i++) { | ||
var d = this.ev.start.getDay() + i; | ||
d = d >= jl ? d - jl : d; | ||
if(jmp[d] !== null) | ||
break; | ||
}; | ||
// avoid falling into the void. start/end date offset correction | ||
if (!this.jumpingVector[this.ev.start.getDay()]) { | ||
var jmp = this.jumpingVector | ||
, jl = jmp.length; | ||
for (var i = 0; i < jl; i++) { | ||
var d = this.ev.start.getDay() + i; | ||
d = d >= jl ? d - jl : d; | ||
if(jmp[d] !== null) | ||
break; | ||
}; | ||
this.ev.start.setDate(this.ev.start.getDate() + i); | ||
this.ev.end.setDate(this.ev.end.getDate() + i); | ||
} | ||
this.ev.start.setDate(this.ev.start.getDate() + i); | ||
this.ev.end.setDate(this.ev.end.getDate() + i); | ||
} | ||
} | ||
// recurrence default value | ||
var rec = this.ev.recurrence || {} | ||
, defVals = { every: 1 | ||
, 'end-by': { | ||
type: 'never' | ||
, after: 7 | ||
, on: null | ||
} | ||
, 'repeat-on': {} | ||
, exceptions: [] | ||
}; | ||
// recurrence default value | ||
var rec = this.ev.recurrence || {} | ||
, defVals = { every: 1 | ||
, 'end-by': { | ||
type: 'never' | ||
, after: 7 | ||
, on: null | ||
} | ||
, 'repeat-on': {} | ||
, exceptions: [] | ||
}; | ||
for (var k in defVals) | ||
if(!rec[k]) | ||
rec[k] = defVals[k]; | ||
for (var k in defVals) | ||
if(!rec[k]) | ||
rec[k] = defVals[k]; | ||
// enf-by on date | ||
if (rec['end-by'].on == 'string') | ||
rec['end-by'].on = new Date(rec['end-by'].on); | ||
// enf-by on date | ||
if (rec['end-by'].on == 'string') | ||
rec['end-by'].on = new Date(rec['end-by'].on); | ||
return this.ev; | ||
} | ||
return this.ev; | ||
} | ||
/** | ||
* getElapsedInstances() | ||
* return elapsed instances of the recurring event in function of date period | ||
* limit | ||
* | ||
* @param {Date} limitDate | ||
* @param {Boolean} addPartialInstance | ||
* | ||
* return {Number} elapsed instances | ||
*/ | ||
/** | ||
* getElapsedInstances() | ||
* return elapsed instances of the recurring event in function of date period | ||
* limit | ||
* | ||
* @param {Date} limitDate | ||
* @param {Boolean} addPartialInstance | ||
* | ||
* return {Number} elapsed instances | ||
*/ | ||
pptSeed.getElapsedInstances = function (limitDate, addPartialInstance) { | ||
// alias | ||
var ev = this.ev | ||
, limitDate = limitDate || this.period.start | ||
, elapsedInstances = 0 | ||
, self = this; | ||
pptSeed.getElapsedInstances = function (limitDate, addPartialInstance) { | ||
// alias | ||
var ev = this.ev | ||
, limitDate = limitDate || this.period.start | ||
, elapsedInstances = 0 | ||
, self = this; | ||
// add partial instance | ||
if (addPartialInstance) { | ||
limitDate = new Date( | ||
+limitDate | ||
+ _date.getDiff(this.ev.end, this.ev.start) - 1); | ||
// add partial instance | ||
if (addPartialInstance) { | ||
limitDate = new Date( | ||
+limitDate | ||
+ _date.getDiff(this.ev.end, this.ev.start) - 1); | ||
var tzdiff = _date.getTZDiff(limitDate, this.ev.start); | ||
if(tzdiff) | ||
limitDate.setMinutes(limitDate.getMinutes() - tzdiff); | ||
} | ||
var tzdiff = _date.getTZDiff(limitDate, this.ev.start); | ||
if(tzdiff) | ||
limitDate.setMinutes(limitDate.getMinutes() - tzdiff); | ||
} | ||
function getDaysByPeriod (ref, daysByPeriod, start) { | ||
var initDate = start || self.ev.start | ||
, endDate = self._getDateNextInstance(ref) | ||
, diffInDays = _date.getDiffInDays(endDate, initDate, 'floor'); | ||
function getDaysByPeriod (ref, daysByPeriod, start) { | ||
var initDate = start || self.ev.start | ||
, endDate = self._getDateNextInstance(ref) | ||
, diffInDays = _date.getDiffInDays(endDate, initDate, 'floor'); | ||
if (self.ev.allDay) { | ||
clearTime(initDate); | ||
} | ||
return Math.ceil(diffInDays / daysByPeriod); | ||
if (self.ev.allDay) { | ||
clearTime(initDate); | ||
} | ||
switch (ev.frequency) { | ||
case 'day': | ||
elapsedInstances = getDaysByPeriod(limitDate, ev.recurrence.every); | ||
break; | ||
return Math.ceil(diffInDays / daysByPeriod); | ||
} | ||
case 'week': | ||
this._walkWeek(this.ev.start, this.ev.start, function (date) { | ||
elapsedInstances += getDaysByPeriod(limitDate | ||
, ev.recurrence.every * 7, date); | ||
}); | ||
break; | ||
switch (ev.frequency) { | ||
case 'day': | ||
elapsedInstances = getDaysByPeriod(limitDate, ev.recurrence.every); | ||
break; | ||
case 'month': | ||
var start = this.ev.start | ||
, end = self._getDateNextInstance(limitDate) | ||
, diffInMonths = _date.getDiffInMonths(end, start); | ||
case 'week': | ||
this._walkWeek(this.ev.start, this.ev.start, function (date) { | ||
elapsedInstances += getDaysByPeriod(limitDate | ||
, ev.recurrence.every * 7, date); | ||
}); | ||
break; | ||
elapsedInstances = Math.ceil(diffInMonths / ev.recurrence.every); | ||
case 'month': | ||
var start = this.ev.start | ||
, end = self._getDateNextInstance(limitDate) | ||
, diffInMonths = _date.getDiffInMonths(end, start); | ||
if (ev.recurrence['repeat-on'].mode == 'day-of-week') { | ||
var endC = new Date(+end + +this.ev.end - this.ev.start); | ||
if (+limitDate >= +endC) | ||
elapsedInstances++; | ||
} | ||
break; | ||
elapsedInstances = Math.ceil(diffInMonths / ev.recurrence.every); | ||
case 'year': | ||
var start = this.ev.start | ||
, end = self._getDateNextInstance(limitDate) | ||
, diffInYears = _date.getDiffInYears(end, start); | ||
if (ev.recurrence['repeat-on'].mode == 'day-of-week') { | ||
var endC = new Date(+end + +this.ev.end - this.ev.start); | ||
if (+limitDate >= +endC) | ||
elapsedInstances++; | ||
} | ||
break; | ||
elapsedInstances = Math.ceil(diffInYears / ev.recurrence.every); | ||
break; | ||
} | ||
case 'year': | ||
var start = this.ev.start | ||
, end = self._getDateNextInstance(limitDate) | ||
, diffInYears = _date.getDiffInYears(end, start); | ||
return elapsedInstances; | ||
elapsedInstances = Math.ceil(diffInYears / ev.recurrence.every); | ||
break; | ||
} | ||
/** | ||
* Generating instances process | ||
* generates (and returns) all instances of recurring seed event passing | ||
* (optionally) start/end period date. | ||
* | ||
* @param {Date} (optional) start: period start date | ||
* @param {Date} (optional) end: period end date | ||
* | ||
* @return {Array} Instances objects Arrays | ||
*/ | ||
return elapsedInstances; | ||
} | ||
pptSeed.genInstances = function (start, end) { | ||
// redefine period | ||
if (start || end) | ||
this.setPeriod(start, end); | ||
/** | ||
* Generating instances process | ||
* generates (and returns) all instances of recurring seed event passing | ||
* (optionally) start/end period date. | ||
* | ||
* @param {Date} (optional) start: period start date | ||
* @param {Date} (optional) end: period end date | ||
* | ||
* @return {Array} Instances objects Arrays | ||
*/ | ||
var instances = []; | ||
pptSeed.genInstances = function (start, end) { | ||
// redefine period | ||
if (start || end) | ||
this.setPeriod(start, end); | ||
// alias | ||
var ev = this.ev | ||
, start = this.period.start | ||
, end = this.period.end | ||
var instances = []; | ||
// add no-recurrence events | ||
if (!ev.frequency) { | ||
if (this.options.addNoRec) { | ||
if ( ev.start >= start && ev.start < end | ||
|| ev.end < end && ev.end >= start | ||
|| ev.start <= start && ev.end >= end | ||
) { | ||
return [new Instance(this, this.ev.start)]; | ||
} | ||
else return[]; | ||
// alias | ||
var ev = this.ev | ||
, start = this.period.start | ||
, end = this.period.end | ||
// add no-recurrence events | ||
if (!ev.frequency) { | ||
if (this.options.addNoRec) { | ||
if ( ev.start >= start && ev.start < end | ||
|| ev.end < end && ev.end >= start | ||
|| ev.start <= start && ev.end >= end | ||
) { | ||
return [new Instance(this, this.ev.start)]; | ||
} | ||
else | ||
return []; | ||
else return[]; | ||
} | ||
else | ||
return []; | ||
} | ||
var cursorDate = this._getDateNextInstance(start) | ||
, jumper = +cursorDate | ||
, n = this.getElapsedInstances(start) | ||
, prevInstance = null | ||
, countdown = this._getCountdown() | ||
, prevInstance = null; | ||
var cursorDate = this._getDateNextInstance(start) | ||
, jumper = +cursorDate | ||
, n = this.getElapsedInstances(start) | ||
, prevInstance = null | ||
, countdown = this._getCountdown() | ||
, prevInstance = null; | ||
while (countdown > 0) { | ||
// exception instances control | ||
var excKey = _date.getFormattedDate(cursorDate, false); | ||
if (ev.recurrence.exceptions.indexOf(excKey) < 0) { | ||
var Inst = new Instance(this, cursorDate); | ||
while (countdown > 0) { | ||
// exception instances control | ||
var excKey = _date.getFormattedDate(cursorDate, false); | ||
if (ev.recurrence.exceptions.indexOf(excKey) < 0) { | ||
var Inst = new Instance(this, cursorDate); | ||
Inst.n = n; | ||
Inst._prevInst = prevInstance; | ||
Inst.n = n; | ||
Inst._prevInst = prevInstance; | ||
instances.push(Inst); | ||
instances.push(Inst); | ||
n++; | ||
prevInstance = Inst; | ||
} | ||
cursorDate = this._getDateNextJump(cursorDate); | ||
countdown--; | ||
n++; | ||
prevInstance = Inst; | ||
} | ||
return instances; | ||
cursorDate = this._getDateNextJump(cursorDate); | ||
countdown--; | ||
} | ||
/** | ||
* get all instances for the given start/end period dates | ||
*/ | ||
return instances; | ||
} | ||
pptSeed.getInstances = function (start, end) { | ||
return this.genInstances(start, end); | ||
} | ||
/** | ||
* get all instances for the given start/end period dates | ||
*/ | ||
pptSeed._walkWeek = function (start, mark, fn) { | ||
var cursorDay = start.getDay() | ||
, addDays = 0 | ||
, jumping = this.jumpingVector; | ||
pptSeed.getInstances = function (start, end) { | ||
return this.genInstances(start, end); | ||
} | ||
mark = new Date(mark) | ||
var prevMark = null | ||
, nextMark = new Date(mark); | ||
pptSeed._walkWeek = function (start, mark, fn) { | ||
var cursorDay = start.getDay() | ||
, addDays = 0 | ||
, jumping = this.jumpingVector; | ||
// walk all days of a block | ||
for (var j = 0; j < jumping.length; j++) { | ||
if (jumping[cursorDay]) { | ||
nextMark.setDate(mark.getDate() + jumping[cursorDay]); | ||
fn(mark, prevMark, nextMark); | ||
mark = new Date(mark) | ||
var prevMark = null | ||
, nextMark = new Date(mark); | ||
// computing next step | ||
prevMark = new Date(mark); | ||
mark.setDate(mark.getDate() + jumping[cursorDay]); | ||
addDays += jumping[cursorDay]; | ||
cursorDay = (cursorDay + jumping[cursorDay]) % jumping.length; | ||
// walk all days of a block | ||
for (var j = 0; j < jumping.length; j++) { | ||
if (jumping[cursorDay]) { | ||
nextMark.setDate(mark.getDate() + jumping[cursorDay]); | ||
fn(mark, prevMark, nextMark); | ||
// break buble | ||
if (cursorDay == start.getDay() && j) | ||
j = jumping.length; | ||
} | ||
else { | ||
throw new Error ('seems cursor day vacuum has fallen'); | ||
} | ||
}; | ||
} | ||
// computing next step | ||
prevMark = new Date(mark); | ||
mark.setDate(mark.getDate() + jumping[cursorDay]); | ||
addDays += jumping[cursorDay]; | ||
cursorDay = (cursorDay + jumping[cursorDay]) % jumping.length; | ||
pptSeed._getCountdown = function () { | ||
// alias | ||
var start = this.period.start | ||
, end = this.period.end | ||
, ev = this.ev; | ||
// break buble | ||
if (cursorDay == start.getDay() && j) | ||
j = jumping.length; | ||
} | ||
else { | ||
throw new Error ('seems cursor day vacuum has fallen'); | ||
} | ||
}; | ||
} | ||
var elapsedInstances = this.getElapsedInstances() | ||
, maxInstances = this.getElapsedInstances(end, true) | ||
, endByInstances = maxInstances; | ||
pptSeed._getCountdown = function () { | ||
// alias | ||
var start = this.period.start | ||
, end = this.period.end | ||
, ev = this.ev; | ||
// computing total instances through start / enda dates limits | ||
switch (ev.recurrence['end-by'].type) { | ||
case 'after': | ||
endByInstances = ev.recurrence['end-by'].after; | ||
break; | ||
var elapsedInstances = this.getElapsedInstances() | ||
, maxInstances = this.getElapsedInstances(end, true) | ||
, endByInstances = maxInstances; | ||
case 'on': | ||
var on = new Date(ev.recurrence['end-by'].on); | ||
on.setDate(on.getDate() + 1); | ||
endByInstances = this.getElapsedInstances(on, true); | ||
break; | ||
} | ||
// computing total instances through start / enda dates limits | ||
switch (ev.recurrence['end-by'].type) { | ||
case 'after': | ||
endByInstances = ev.recurrence['end-by'].after; | ||
break; | ||
var total = Math.min(maxInstances, endByInstances); | ||
return Math.max(total - elapsedInstances, 0); | ||
case 'on': | ||
var on = new Date(ev.recurrence['end-by'].on); | ||
on.setDate(on.getDate() + 1); | ||
endByInstances = this.getElapsedInstances(on, true); | ||
break; | ||
} | ||
/** | ||
* setJumpingVector() | ||
* return Array with the jump day by day for 'weekly' mode | ||
* | ||
* @param {Object Event} | ||
* return {Array} jumping vector | ||
*/ | ||
var total = Math.min(maxInstances, endByInstances); | ||
return Math.max(total - elapsedInstances, 0); | ||
} | ||
pptSeed.setJumpingVector = function () { | ||
var ev = this.ev; | ||
/** | ||
* setJumpingVector() | ||
* return Array with the jump day by day for 'weekly' mode | ||
* | ||
* @param {Object Event} | ||
* return {Array} jumping vector | ||
*/ | ||
var cd = null | ||
, pd = null | ||
, fd = null | ||
, jumpingVector = [null, null, null, null, null, null, null ] | ||
, repOn = ev.recurrence['repeat-on'] | ||
pptSeed.setJumpingVector = function () { | ||
var ev = this.ev; | ||
// build repeat on Array | ||
// contains all days sorting by day number | ||
var repOnArr = []; | ||
for (var kd in repOn) | ||
repOnArr.push (kd); | ||
var cd = null | ||
, pd = null | ||
, fd = null | ||
, jumpingVector = [null, null, null, null, null, null, null ] | ||
, repOn = ev.recurrence['repeat-on'] | ||
repOnArr.sort (function (e0, e1) { | ||
return _c.daysMap[e0] > _c.daysMap[e1] ? 1 : -1; | ||
}); | ||
// build repeat on Array | ||
// contains all days sorting by day number | ||
var repOnArr = []; | ||
for (var kd in repOn) | ||
repOnArr.push (kd); | ||
// building jumping vector - determined jump for each day number | ||
// [S, M, T, W, T, F, S] | ||
for (var kdi = 0; kdi < repOnArr.length; kdi++) { | ||
var kd = repOnArr[kdi]; | ||
cd = _c.daysMap[kd]; | ||
repOnArr.sort (function (e0, e1) { | ||
return _c.daysMap[e0] > _c.daysMap[e1] ? 1 : -1; | ||
}); | ||
if (pd === null) | ||
fd = cd; | ||
else | ||
jumpingVector[pd] = cd - pd; | ||
// building jumping vector - determined jump for each day number | ||
// [S, M, T, W, T, F, S] | ||
for (var kdi = 0; kdi < repOnArr.length; kdi++) { | ||
var kd = repOnArr[kdi]; | ||
cd = _c.daysMap[kd]; | ||
pd = cd; | ||
}; | ||
if (pd === null) | ||
fd = cd; | ||
else | ||
jumpingVector[pd] = cd - pd; | ||
// last jump day every correction | ||
jumpingVector[cd] = 7 * ev.recurrence.every - pd + fd; | ||
pd = cd; | ||
}; | ||
return this.jumpingVector = jumpingVector; | ||
} | ||
// last jump day every correction | ||
jumpingVector[cd] = 7 * ev.recurrence.every - pd + fd; | ||
/** | ||
* _getJumpingVector | ||
*/ | ||
return this.jumpingVector = jumpingVector; | ||
} | ||
pptSeed._getJumpingVector = function () { | ||
return this.jumpingVector; | ||
} | ||
/** | ||
* _getJumpingVector | ||
*/ | ||
/** | ||
* _getDateInstance() | ||
*/ | ||
pptSeed._getJumpingVector = function () { | ||
return this.jumpingVector; | ||
} | ||
pptSeed._getDateInstance = function (_limit, dir) { | ||
var ev = this.ev; | ||
/** | ||
* _getDateInstance() | ||
*/ | ||
limit = new Date(_limit || this.period.start); | ||
dir = dir || 'prev'; | ||
pptSeed._getDateInstance = function (_limit, dir) { | ||
var ev = this.ev; | ||
var prev = dir == 'prev' | ||
, mark = new Date(prev ? +ev.start : +ev.end); | ||
limit = new Date(_limit || this.period.start); | ||
dir = dir || 'prev'; | ||
// allDay - limit date correction | ||
if (this.ev.allDay) { | ||
clearTime(mark); | ||
if (!prev) { | ||
mark.setDate(mark.getDate() + 1); | ||
} | ||
var prev = dir == 'prev' | ||
, mark = new Date(prev ? +ev.start : +ev.end); | ||
// allDay - limit date correction | ||
if (this.ev.allDay) { | ||
clearTime(mark); | ||
if (!prev) { | ||
mark.setDate(mark.getDate() + 1); | ||
} | ||
} | ||
if(mark > limit) | ||
return new Date(ev.start); | ||
if(mark > limit) | ||
return new Date(ev.start); | ||
var newDate = new Date(ev.start); | ||
var newDate = new Date(ev.start); | ||
function getPeriods() { | ||
var diff = _date.getDiffInDays(limit, mark, 'floor') | ||
, pDays = ev.recurrence.every; | ||
function getPeriods() { | ||
var diff = _date.getDiffInDays(limit, mark, 'floor') | ||
, pDays = ev.recurrence.every; | ||
if (ev.frequency == 'week') | ||
pDays *= 7; | ||
if (ev.frequency == 'week') | ||
pDays *= 7; | ||
return Math.floor(diff / pDays); | ||
} | ||
return Math.floor(diff / pDays); | ||
} | ||
switch (ev.frequency) { | ||
case 'day': | ||
var days = newDate.getDate() | ||
+ (getPeriods() + (prev ? 0 : 1)) * ev.recurrence.every; | ||
switch (ev.frequency) { | ||
case 'day': | ||
var days = newDate.getDate() | ||
+ (getPeriods() + (prev ? 0 : 1)) * ev.recurrence.every; | ||
newDate.setDate(days); | ||
break; | ||
newDate.setDate(days); | ||
break; | ||
case 'week': | ||
var offset = getPeriods() * (ev.recurrence.every * 7); | ||
var wlimit = new Date(+limit - (_date.getDiff(mark, ev.start))); | ||
case 'week': | ||
var offset = getPeriods() * (ev.recurrence.every * 7); | ||
var wlimit = new Date(+limit - (_date.getDiff(mark, ev.start))); | ||
_date.applyTZCorrection(wlimit, limit, -1); | ||
_date.applyTZCorrection(wlimit, limit, -1); | ||
this._walkWeek(ev.start, +ev.start, function (date, prevDate, nextDate) { | ||
date = new Date(date); | ||
date.setDate(date.getDate() + offset); | ||
this._walkWeek(ev.start, +ev.start, function (date, prevDate, nextDate) { | ||
date = new Date(date); | ||
date.setDate(date.getDate() + offset); | ||
nextDate = new Date(nextDate); | ||
nextDate.setDate(nextDate.getDate() + offset); | ||
nextDate = new Date(nextDate); | ||
nextDate.setDate(nextDate.getDate() + offset); | ||
@@ -513,115 +508,104 @@ // date.setMinutes(date.getMinutes() - _date.getTZDiff(limit, mark)); | ||
if(wlimit >= date) | ||
newDate = new Date(prev ? date : nextDate); | ||
if(wlimit >= date) | ||
newDate = new Date(prev ? date : nextDate); | ||
}); | ||
break; | ||
}); | ||
break; | ||
case 'month': | ||
var diffInMonths = _date.getDiffInMonths(limit, mark, true) | ||
, periods = Math.max(0, (diffInMonths / ev.recurrence.every | 0)); | ||
case 'month': | ||
var diffInMonths = _date.getDiffInMonths(limit, mark, true) | ||
, periods = Math.max(0, (diffInMonths / ev.recurrence.every | 0)); | ||
if (ev.recurrence['repeat-on'].mode == 'day-of-month') { | ||
// periods dir correction | ||
periods+= prev ? 0 : 1; | ||
if (ev.recurrence['repeat-on'].mode == 'day-of-month') { | ||
// periods dir correction | ||
periods+= prev ? 0 : 1; | ||
var monthNumber = newDate.getMonth() + ev.recurrence.every * periods; | ||
var monthNumber = newDate.getMonth() + ev.recurrence.every * periods; | ||
// existance day in next month control | ||
var tmpDate = new Date(newDate); | ||
tmpDate.setDate(1); | ||
tmpDate.setMonth(monthNumber); | ||
// existance day in next month control | ||
var tmpDate = new Date(newDate); | ||
tmpDate.setDate(1); | ||
tmpDate.setMonth(monthNumber); | ||
if(_date.getDaysInMonth(tmpDate) >= newDate.getDate()) | ||
newDate.setMonth(monthNumber); | ||
else | ||
newDate.setMonth(monthNumber + ev.recurrence.every); | ||
} | ||
else { | ||
var diffInMonths = _date.getDiffInMonths(limit, mark) | ||
, periods = Math.max(0, (diffInMonths / ev.recurrence.every | 0)); | ||
if(_date.getDaysInMonth(tmpDate) >= newDate.getDate()) | ||
newDate.setMonth(monthNumber); | ||
else | ||
newDate.setMonth(monthNumber + ev.recurrence.every); | ||
} | ||
else { | ||
var diffInMonths = _date.getDiffInMonths(limit, mark) | ||
, periods = Math.max(0, (diffInMonths / ev.recurrence.every | 0)); | ||
// mode: day-of-week | ||
var nW = _date.getWeekOfDay(this.ev.start) | ||
, nD = this.ev.start.getDay(); | ||
// mode: day-of-week | ||
var nW = _date.getWeekOfDay(this.ev.start) | ||
, nD = this.ev.start.getDay(); | ||
mark = new Date(ev.start); | ||
mark.setMonth(mark.getMonth() + ev.recurrence.every * periods); | ||
mark = new Date(ev.start); | ||
mark.setMonth(mark.getMonth() + ev.recurrence.every * periods); | ||
_date.setByWeekAndDay(mark, nW, nD); | ||
_date.setByWeekAndDay(mark, nW, nD); | ||
// move to end of mark if is 'next' direction | ||
if (!prev) | ||
mark = new Date(+mark + _date.getDiff(ev.end, ev.start) - 1); | ||
// move to end of mark if is 'next' direction | ||
if (!prev) | ||
mark = new Date(+mark + _date.getDiff(ev.end, ev.start) - 1); | ||
// periods offset correction | ||
periods += (limit <= mark ? -1 : 0) + (prev ? 0 : 1); | ||
// periods offset correction | ||
periods += (limit <= mark ? -1 : 0) + (prev ? 0 : 1); | ||
newDate.setMonth(newDate.getMonth() + ev.recurrence.every * periods); | ||
_date.setByWeekAndDay(newDate, nW, nD); | ||
} | ||
break; | ||
newDate.setMonth(newDate.getMonth() + ev.recurrence.every * periods); | ||
_date.setByWeekAndDay(newDate, nW, nD); | ||
} | ||
break; | ||
case 'year': | ||
var diffInYears = _date.getDiffInYears(limit, mark, true); | ||
case 'year': | ||
var diffInYears = _date.getDiffInYears(limit, mark, true); | ||
if (dir == 'next') | ||
diffInYears+= ev.recurrence.every; | ||
if (dir == 'next') | ||
diffInYears+= ev.recurrence.every; | ||
var period = diffInYears /ev.recurrence.every | 0; | ||
newDate.setFullYear(newDate.getFullYear() + period * ev.recurrence.every); | ||
break; | ||
} | ||
return newDate; | ||
var period = diffInYears /ev.recurrence.every | 0; | ||
newDate.setFullYear(newDate.getFullYear() + period * ev.recurrence.every); | ||
break; | ||
} | ||
/** | ||
* _getDatePrevInstance() | ||
* return a date of previous instance. | ||
* | ||
* @param {Date} ref: reference to computing | ||
* | ||
* return {Date} | ||
*/ | ||
return newDate; | ||
} | ||
pptSeed._getDatePrevInstance = function (ref) { | ||
return this._getDateInstance(ref); | ||
} | ||
/** | ||
* _getDatePrevInstance() | ||
* return a date of previous instance. | ||
* | ||
* @param {Date} ref: reference to computing | ||
* | ||
* return {Date} | ||
*/ | ||
/** | ||
* _getDateNextInstance() | ||
*/ | ||
pptSeed._getDatePrevInstance = function (ref) { | ||
return this._getDateInstance(ref); | ||
} | ||
pptSeed._getDateNextInstance = function (ref) { | ||
var next = this._getDateInstance(ref, 'next'); | ||
return next; | ||
} | ||
/** | ||
* _getDateNextInstance() | ||
*/ | ||
/** | ||
* _getDateNextJump() | ||
*/ | ||
pptSeed._getDateNextInstance = function (ref) { | ||
var next = this._getDateInstance(ref, 'next'); | ||
return next; | ||
} | ||
pptSeed._getDateNextJump = function (_ref) { | ||
/** | ||
* _getDateNextJump() | ||
*/ | ||
var ref = new Date(+_ref + (_date.getDiff(this.ev.end, this.ev.start))) | ||
_date.applyTZCorrection(ref, _ref); | ||
pptSeed._getDateNextJump = function (_ref) { | ||
if (this.ev.allDay) { | ||
clearTime(ref); | ||
ref.setDate(ref.getDate() + 1); | ||
} | ||
var ref = new Date(+_ref + (_date.getDiff(this.ev.end, this.ev.start))) | ||
_date.applyTZCorrection(ref, _ref); | ||
return this._getDateInstance(ref, 'next'); | ||
if (this.ev.allDay) { | ||
clearTime(ref); | ||
ref.setDate(ref.getDate() + 1); | ||
} | ||
// client-side: add caTools global var | ||
if (!serverSide) { | ||
if (typeof window.caTools == 'undefined') | ||
window.caTools = {}; | ||
window.caTools.Seed = modSeed; | ||
} | ||
})(typeof module != 'undefined' ? module : {}, typeof window != 'object'); | ||
return this._getDateInstance(ref, 'next'); | ||
} |
746
lib/util.js
/*! | ||
* util usefull functions | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
* util usefull functions | ||
* Copyright(c) 2011 Damian Suarez <rdsuarez@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
/** | ||
* time constants | ||
*/ | ||
// by-side behavour | ||
(function(module, serverSide) { | ||
if (typeof module.exports == 'undefined') | ||
module.exports = {}; | ||
var _minute = 1000 * 60 | ||
, _hour = _minute*60 | ||
, _day = _hour*24 | ||
, _week = _day * 7; | ||
/** | ||
* Module dependecies | ||
*/ | ||
/** | ||
* days map | ||
* used in weekly mode process. | ||
*/ | ||
// time is fake in client-side | ||
var time = serverSide ? require('time') : {}; | ||
var daysMap = { su: 0, m: 1, t: 2, w: 3, th: 4, f: 5, sa: 6 }; | ||
/** | ||
* time constants | ||
*/ | ||
/** | ||
* timezone correction | ||
* @param {Number} tz | ||
*/ | ||
var _minute = 1000 * 60 | ||
, _hour = _minute*60 | ||
, _day = _hour*24 | ||
, _week = _day * 7; | ||
function tzCorrection (date, tz) { | ||
return date = new Date(+date - tz * _hour); | ||
} | ||
/** | ||
* days map | ||
* used in weekly mode process. | ||
*/ | ||
var daysMap = { su: 0, m: 1, t: 2, w: 3, th: 4, f: 5, sa: 6 }; | ||
/************************** | ||
* date usefull functions * | ||
**************************/ | ||
/** | ||
* timezone correction | ||
* @param {Number} tz | ||
*/ | ||
var _date = module.exports.date = {}; | ||
function tzCorrection (date, tz) { | ||
return date = new Date(+date - tz * _hour); | ||
} | ||
/** | ||
* exports constants | ||
*/ | ||
_date.const = { | ||
minute: _minute | ||
, hour: _hour | ||
, day: _day | ||
, week: _week | ||
, daysMap: daysMap | ||
} | ||
/************************** | ||
* date usefull functions * | ||
**************************/ | ||
/** | ||
* clearTime() | ||
* | ||
* @param {Date} date: date to clear time | ||
* @para, {Boolean} clone: if is true clones new date | ||
* | ||
* return {Date} date | ||
*/ | ||
var _date = module.exports.date = {}; | ||
var clearTime = _date.clearTime = function (date, clone) { | ||
var _date = date; | ||
/** | ||
* exports constants | ||
*/ | ||
if (clone) | ||
_date = new Date(date); | ||
_date.const = { | ||
minute: _minute | ||
, hour: _hour | ||
, day: _day | ||
, week: _week | ||
, daysMap: daysMap | ||
} | ||
else if (typeof date == 'number') | ||
_date = new Date(Number(date)); | ||
/** | ||
* clearTime() | ||
* | ||
* @param {Date} date: date to clear time | ||
* @para, {Boolean} clone: if is true clones new date | ||
* | ||
* return {Date} date | ||
*/ | ||
_date.setMilliseconds (0); | ||
_date.setSeconds (0); | ||
_date.setMinutes (0); | ||
_date.setHours (0); | ||
var clearTime = _date.clearTime = function (date, clone) { | ||
var _date = date; | ||
return _date; | ||
} | ||
if (clone) | ||
_date = new Date(date); | ||
/** | ||
* Returns if a certain year is a leap year | ||
*/ | ||
else if (typeof date == 'number') | ||
_date = new Date(Number(date)); | ||
_date.isLeapYear = function (year){ | ||
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); | ||
}; | ||
_date.setMilliseconds (0); | ||
_date.setSeconds (0); | ||
_date.setMinutes (0); | ||
_date.setHours (0); | ||
/** | ||
* Returns days in a month by year | ||
*/ | ||
return _date; | ||
} | ||
_date.getDaysInMonth = function (){ | ||
var args = arguments | ||
, year = args[0] instanceof Date ? args[0].getFullYear() : args[0] | ||
, month = args[0] instanceof Date ? args[0].getMonth() : args[1]; | ||
/** | ||
* Returns if a certain year is a leap year | ||
*/ | ||
return [31, (_date.isLeapYear(year) ? 29 : 28), 31, 30, 31, | ||
30, 31, 31, 30, 31, 30, 31][month]; | ||
}; | ||
_date.isLeapYear = function (year){ | ||
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); | ||
}; | ||
/** | ||
* Apply timezone diff correctio | ||
*/ | ||
/** | ||
* Returns days in a month by year | ||
*/ | ||
_date.applyTZCorrection = function (date, dateToCompare, sign) { | ||
sign = sign || 1; | ||
var tzdiff = _date.getTZDiff(date, dateToCompare); | ||
_date.getDaysInMonth = function (){ | ||
var args = arguments | ||
, year = args[0] instanceof Date ? args[0].getFullYear() : args[0] | ||
, month = args[0] instanceof Date ? args[0].getMonth() : args[1]; | ||
if (tzdiff) | ||
date.setMinutes(date.getMinutes() + tzdiff * sign) | ||
return [31, (_date.isLeapYear(year) ? 29 : 28), 31, 30, 31, | ||
30, 31, 31, 30, 31, 30, 31][month]; | ||
}; | ||
return date; | ||
} | ||
/** | ||
* Apply timezone diff correctio | ||
*/ | ||
/** | ||
* getTZDiff() | ||
* returns the timezone difference between given dates | ||
*/ | ||
_date.applyTZCorrection = function (date, dateToCompare, sign) { | ||
sign = sign || 1; | ||
var tzdiff = _date.getTZDiff(date, dateToCompare); | ||
_date.getTZDiff = function (end, start) { | ||
return end.getTimezoneOffset() - start.getTimezoneOffset() | ||
} | ||
if (tzdiff) | ||
date.setMinutes(date.getMinutes() + tzdiff * sign) | ||
/** | ||
* diff in milliseconds | ||
* support Dylight saving time nightmare correction. | ||
*/ | ||
return date; | ||
} | ||
_date.getDiff = function (end, start) { | ||
var dim = _date.getTZDiff(end, start) * _minute | ||
, diff = end.getTime() - start.getTime() + dim; | ||
return diff; | ||
} | ||
/** | ||
* getTZDiff() | ||
* returns the timezone difference between given dates | ||
*/ | ||
/** | ||
* diff in days | ||
* support Dylight saving time nightmare correction. | ||
*/ | ||
_date.getTZDiff = function (end, start) { | ||
return end.getTimezoneOffset() - start.getTimezoneOffset() | ||
} | ||
_date.getDiffInDays = function (end, start, mtd) { | ||
var diff = _date.getDiff(end, start); | ||
mtd = mtd || 'ceil'; | ||
return Math[mtd](diff / _day); | ||
} | ||
/** | ||
* diff in milliseconds | ||
* support Dylight saving time nightmare correction. | ||
*/ | ||
_date.getDiff = function (end, start) { | ||
var dim = _date.getTZDiff(end, start) * _minute | ||
, diff = end.getTime() - start.getTime() + dim; | ||
return diff; | ||
} | ||
/** | ||
* getDiffInMonths() | ||
*/ | ||
/** | ||
* diff in days | ||
* support Dylight saving time nightmare correction. | ||
*/ | ||
_date.getDiffInMonths = function (end, start, noRound) { | ||
var tempStart = new Date(start) | ||
, tempEnd = new Date(end); | ||
_date.getDiffInDays = function (end, start, mtd) { | ||
var diff = _date.getDiff(end, start); | ||
mtd = mtd || 'ceil'; | ||
return Math[mtd](diff / _day); | ||
} | ||
tempStart.setFullYear(2000); | ||
tempEnd.setFullYear(2000); | ||
tempStart.setMonth(0); | ||
tempEnd.setMonth(0); | ||
/** | ||
* getDiffInMonths() | ||
*/ | ||
var less = tempEnd < tempStart && noRound ? 1 : 0; | ||
return (end.getFullYear() - start.getFullYear()) * 12 | ||
+ (end.getMonth() - start.getMonth() - less); | ||
} | ||
_date.getDiffInMonths = function (end, start, noRound) { | ||
var tempStart = new Date(start) | ||
, tempEnd = new Date(end); | ||
/** | ||
* getDiffInMonths() | ||
*/ | ||
tempStart.setFullYear(2000); | ||
tempEnd.setFullYear(2000); | ||
_date.getDiffInYears = function (end, start, noRound) { | ||
return _date.getDiffInMonths(end, start, noRound) / 12 | 0; | ||
} | ||
tempStart.setMonth(0); | ||
tempEnd.setMonth(0); | ||
/** | ||
* getFormattedDate() | ||
* | ||
* @paramn {Date} date | ||
* @param {Boolean} cp: complete format date with zeros | ||
* | ||
* return {String} date: eg 07/18/1977 | ||
*/ | ||
var less = tempEnd < tempStart && noRound ? 1 : 0; | ||
return (end.getFullYear() - start.getFullYear()) * 12 | ||
+ (end.getMonth() - start.getMonth() - less); | ||
} | ||
var getFormattedDate = _date.getFormattedDate = function (date, cp) { | ||
var d = date.getDate() | ||
, m = date.getMonth() + 1 | ||
var arrDate = [ | ||
cp && m < 10 ? '0' + m : m | ||
, cp && d < 10 ? '0' + d : d | ||
, date.getFullYear() | ||
] | ||
/** | ||
* getDiffInMonths() | ||
*/ | ||
return arrDate.join('/'); | ||
} | ||
_date.getDiffInYears = function (end, start, noRound) { | ||
return _date.getDiffInMonths(end, start, noRound) / 12 | 0; | ||
} | ||
/** | ||
* getFormattedTime() | ||
* return hh:mm tt string | ||
*/ | ||
/** | ||
* getFormattedDate() | ||
* | ||
* @paramn {Date} date | ||
* @param {Boolean} cp: complete format date with zeros | ||
* | ||
* return {String} date: eg 07/18/1977 | ||
*/ | ||
var getFormattedTime = _date.getFormattedTime = function (date) { | ||
var h = date.getHours() | ||
, m = date.getMinutes() | ||
, s = date.getSeconds() | ||
, ampm = h < 12 ? 'AM' : 'PM'; | ||
var getFormattedDate = _date.getFormattedDate = function (date, cp) { | ||
var d = date.getDate() | ||
, m = date.getMonth() + 1 | ||
var arrDate = [ | ||
cp && m < 10 ? '0' + m : m | ||
, cp && d < 10 ? '0' + d : d | ||
, date.getFullYear() | ||
] | ||
h = !h ? 12 : (h > 12 ? (h - 12) : h); | ||
return arrDate.join('/'); | ||
} | ||
return (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ' ' + ampm; | ||
} | ||
/** | ||
* getFormattedTime() | ||
* return hh:mm tt string | ||
*/ | ||
/** | ||
* Returns number of week for the date into current view | ||
* @param {Date Object} date | ||
* @return {Number} | ||
*/ | ||
var getFormattedTime = _date.getFormattedTime = function (date) { | ||
var h = date.getHours() | ||
, m = date.getMinutes() | ||
, s = date.getSeconds() | ||
, ampm = h < 12 ? 'AM' : 'PM'; | ||
var getWeekOfDay = _date.getWeekOfDay = function (date) { | ||
return Math.floor( (date.getDate() - 1 ) / 7); | ||
} | ||
h = !h ? 12 : (h > 12 ? (h - 12) : h); | ||
/** | ||
* setByWeekAndDay() | ||
* | ||
* set date passing week and day number. | ||
* @param {Date} date: date to modify | ||
* @param {String|Number} week: week number (row) | ||
* @param {String|Number} day: day number (col) | ||
* | ||
* return {Date} | ||
* | ||
* eg: Oct 2011 | ||
* | ||
* S M T W Th F Sa | ||
* 0 1 2 3 4 5 6 | ||
* ------------------------------ | ||
* | 25 26 27 28 29 30 1 | | ||
* | 2 3 4 5 6 7 8 | | ||
* | 9 10 11 12 13 14 15 | | ||
* | 16 17 18 19 20 21 22 | | ||
* | 23 24 25 26 27 28 29 | | ||
* | 30 31 1 2 3 4 5 | | ||
* ------------------------------ | ||
* | ||
* week number is always into date month | ||
* | ||
* var d = new Date (2011, 9, 1); | ||
* setByWeekAndDay (d, 0, 6) -> Sat, 01 Oct 2011 | ||
* setByWeekAndDay (d, 0, 1) -> Mon, 04 Oct 2011 | ||
* setByWeekAndDay (d, 2, 4) -> Thu, 20 Oct 2011 | ||
* | ||
*/ | ||
return (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ' ' + ampm; | ||
} | ||
var setByWeekAndDay = _date.setByWeekAndDay = function (date, week, day) { | ||
var d = new Date(date); | ||
d.setDate(1); | ||
/** | ||
* Returns number of week for the date into current view | ||
* @param {Date Object} date | ||
* @return {Number} | ||
*/ | ||
var getWeekOfDay = _date.getWeekOfDay = function (date) { | ||
return Math.floor( (date.getDate() - 1 ) / 7); | ||
} | ||
var diff = d.getDay() - day | ||
, n = (week + 1) * 7 - diff + 1; | ||
/** | ||
* setByWeekAndDay() | ||
* | ||
* set date passing week and day number. | ||
* @param {Date} date: date to modify | ||
* @param {String|Number} week: week number (row) | ||
* @param {String|Number} day: day number (col) | ||
* | ||
* return {Date} | ||
* | ||
* eg: Oct 2011 | ||
* | ||
* S M T W Th F Sa | ||
* 0 1 2 3 4 5 6 | ||
* ------------------------------ | ||
* | 25 26 27 28 29 30 1 | | ||
* | 2 3 4 5 6 7 8 | | ||
* | 9 10 11 12 13 14 15 | | ||
* | 16 17 18 19 20 21 22 | | ||
* | 23 24 25 26 27 28 29 | | ||
* | 30 31 1 2 3 4 5 | | ||
* ------------------------------ | ||
* | ||
* week number is always into date month | ||
* | ||
* var d = new Date (2011, 9, 1); | ||
* setByWeekAndDay (d, 0, 6) -> Sat, 01 Oct 2011 | ||
* setByWeekAndDay (d, 0, 1) -> Mon, 04 Oct 2011 | ||
* setByWeekAndDay (d, 2, 4) -> Thu, 20 Oct 2011 | ||
* | ||
*/ | ||
n = diff <= 0 ? n - 7 : n; | ||
var setByWeekAndDay = _date.setByWeekAndDay = function (date, week, day) { | ||
var d = new Date(date); | ||
d.setDate(1); | ||
d.setDate(n); | ||
if (_date.getDiffInMonths(d, date)) | ||
n -= 7; | ||
var diff = d.getDay() - day | ||
, n = (week + 1) * 7 - diff + 1; | ||
date.setDate(n); | ||
n = diff <= 0 ? n - 7 : n; | ||
return date; | ||
} | ||
d.setDate(n); | ||
if (_date.getDiffInMonths(d, date)) | ||
n -= 7; | ||
/** | ||
* fixDate | ||
* copied from fullCalendar | ||
*/ | ||
date.setDate(n); | ||
return date; | ||
} | ||
/** | ||
* fixDate | ||
* copied from fullCalendar | ||
*/ | ||
function fixDate(d, check) { | ||
// force d to be on check's YMD, for daylight savings purposes | ||
if (+d) { // prevent infinite looping on invalid dates | ||
while (d.getDate() != check.getDate()) { | ||
d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS); | ||
} | ||
function fixDate(d, check) { | ||
// force d to be on check's YMD, for daylight savings purposes | ||
if (+d) { // prevent infinite looping on invalid dates | ||
while (d.getDate() != check.getDate()) { | ||
d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS); | ||
} | ||
} | ||
} | ||
/** | ||
* parseISO8601 - copied form fullCalendar | ||
*/ | ||
/** | ||
* parseISO8601 - copied form fullCalendar | ||
*/ | ||
var parseISO8601 = _date.parseISO8601 = function (s, ignoreTimezone) { | ||
if (typeof s != 'string') | ||
return s; | ||
var parseISO8601 = _date.parseISO8601 = function (s, ignoreTimezone) { | ||
if (typeof s != 'string') | ||
return s; | ||
// ignoreTimezone defaults to false | ||
// derived from http://delete.me.uk/2005/03/iso8601.html | ||
// TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html | ||
var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/); | ||
if (!m) | ||
return null; | ||
// ignoreTimezone defaults to false | ||
// derived from http://delete.me.uk/2005/03/iso8601.html | ||
// TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html | ||
var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/); | ||
if (!m) | ||
return null; | ||
var date = new Date(m[1], 0, 1); | ||
var date = new Date(m[1], 0, 1); | ||
if (ignoreTimezone || !m[14]) { | ||
var check = new Date(m[1], 0, 1, 9, 0); | ||
if (m[3]) { | ||
date.setMonth(m[3] - 1); | ||
check.setMonth(m[3] - 1); | ||
} | ||
if (m[5]) { | ||
date.setDate(m[5]); | ||
check.setDate(m[5]); | ||
} | ||
fixDate(date, check); | ||
if (m[7]) { | ||
date.setHours(m[7]); | ||
} | ||
if (m[8]) { | ||
date.setMinutes(m[8]); | ||
} | ||
if (m[10]) { | ||
date.setSeconds(m[10]); | ||
} | ||
if (m[12]) { | ||
date.setMilliseconds(Number("0." + m[12]) * 1000); | ||
} | ||
fixDate(date, check); | ||
if (ignoreTimezone || !m[14]) { | ||
var check = new Date(m[1], 0, 1, 9, 0); | ||
if (m[3]) { | ||
date.setMonth(m[3] - 1); | ||
check.setMonth(m[3] - 1); | ||
} | ||
else { | ||
date.setUTCFullYear( | ||
m[1] | ||
, m[3] ? m[3] - 1 : 0 | ||
, m[5] || 1 | ||
); | ||
date.setUTCHours( | ||
m[7] || 0 | ||
, m[8] || 0 | ||
, m[10] || 0 | ||
, m[12] ? Number("0." + m[12]) * 1000 : 0 | ||
); | ||
var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0); | ||
offset *= m[15] == '-' ? 1 : -1; | ||
date = new Date(+date + (offset * 60 * 1000)); | ||
if (m[5]) { | ||
date.setDate(m[5]); | ||
check.setDate(m[5]); | ||
} | ||
fixDate(date, check); | ||
if (m[7]) { | ||
date.setHours(m[7]); | ||
} | ||
if (m[8]) { | ||
date.setMinutes(m[8]); | ||
} | ||
if (m[10]) { | ||
date.setSeconds(m[10]); | ||
} | ||
if (m[12]) { | ||
date.setMilliseconds(Number("0." + m[12]) * 1000); | ||
} | ||
fixDate(date, check); | ||
} | ||
else { | ||
date.setUTCFullYear( | ||
m[1] | ||
, m[3] ? m[3] - 1 : 0 | ||
, m[5] || 1 | ||
); | ||
date.setUTCHours( | ||
m[7] || 0 | ||
, m[8] || 0 | ||
, m[10] || 0 | ||
, m[12] ? Number("0." + m[12]) * 1000 : 0 | ||
); | ||
return date; | ||
var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0); | ||
offset *= m[15] == '-' ? 1 : -1; | ||
date = new Date(+date + (offset * 60 * 1000)); | ||
} | ||
/** | ||
* parse from weird ISO format | ||
*/ | ||
return date; | ||
} | ||
_date.parseFromWeirdISOFormat = function (d, tz) { | ||
var parts = d.match(/(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)/); | ||
/** | ||
* parse from weird ISO format | ||
*/ | ||
if (!parts) { | ||
var simple = d.match(/(\d\d\d\d)(\d\d)(\d\d)/); | ||
if (!simple) return; | ||
_date.parseFromWeirdISOFormat = function (d, tz) { | ||
var parts = d.match(/(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)/); | ||
return new Date(simple[1], simple[2] -1, simple[3]); | ||
} | ||
if (!parts) { | ||
var simple = d.match(/(\d\d\d\d)(\d\d)(\d\d)/); | ||
if (!simple) return; | ||
var date = new Date(); | ||
if (tz) { | ||
time.extend(date); | ||
date.setTimezone(tz); | ||
}; | ||
return new Date(simple[1], simple[2] -1, simple[3]); | ||
} | ||
date.setFullYear(parts[1]); | ||
date.setMonth(parts[2] - 1); | ||
date.setDate(parts[3]); | ||
var date = new Date(); | ||
// @TODO | ||
// consedire apply timezone location in the future | ||
/* | ||
if (tz) { | ||
time.extend(date); | ||
date.setTimezone(tz); | ||
}; | ||
*/ | ||
date.setHours(parts[4]); | ||
date.setMinutes(parts[5]); | ||
date.setSeconds(parts[6]); | ||
date.setFullYear(parts[1]); | ||
date.setMonth(parts[2] - 1); | ||
date.setDate(parts[3]); | ||
date.setMilliseconds(0); | ||
date.setHours(parts[4]); | ||
date.setMinutes(parts[5]); | ||
date.setSeconds(parts[6]); | ||
return date; | ||
}; | ||
date.setMilliseconds(0); | ||
/** | ||
* parse date from TZID format | ||
*/ | ||
return date; | ||
}; | ||
_date.parsefromTZID = function (v) { | ||
var parts = v.match(/TZID=([^:]+):(\d+)T(\d+)/); | ||
if (!parts) return; | ||
/** | ||
* parse date from TZID format | ||
*/ | ||
var date = parseDate.fromWeirdISOFormat(parts[2] + 'T' + parts[3], parts[1]); | ||
_date.parsefromTZID = function (v) { | ||
var parts = v.match(/TZID=([^:]+):(\d+)T(\d+)/); | ||
if (!parts) return; | ||
// debug: TZID parsed with date %s, date | ||
return date; | ||
}; | ||
var date = parseDate.fromWeirdISOFormat(parts[2] + 'T' + parts[3], parts[1]); | ||
// debug: TZID parsed with date %s, date | ||
return date; | ||
}; | ||
/*************************** | ||
* string usefull functions * | ||
***************************/ | ||
/** | ||
* Escape a string with html entities | ||
* | ||
* @param {String} string to escape | ||
* @api public | ||
*/ | ||
/*************************** | ||
* string usefull functions * | ||
***************************/ | ||
var _string = module.exports.string = {}; | ||
/** | ||
* Escape a string with html entities | ||
* | ||
* @param {String} string to escape | ||
* @api public | ||
*/ | ||
_string.escape = function (str){ | ||
return str | ||
.replace(/&/g, '&') | ||
.replace(/>/g, '>') | ||
.replace(/</g, '<') | ||
.replace(/"/g, '"'); | ||
}; | ||
var _string = module.exports.string = {}; | ||
_string.attr = function (str) { | ||
return str ? str.replace(/"/g, '\\"') : ''; | ||
}; | ||
_string.escape = function (str){ | ||
return str | ||
.replace(/&/g, '&') | ||
.replace(/>/g, '>') | ||
.replace(/</g, '<') | ||
.replace(/"/g, '"'); | ||
}; | ||
_string.content = function (str) { | ||
return str ? _string.escape(str) : ''; | ||
}; | ||
_string.attr = function (str) { | ||
return str ? str.replace(/"/g, '\\"') : ''; | ||
}; | ||
/** | ||
* date method | ||
* @param {Date} v: date object | ||
* @param {Boolean} a: all-day | ||
* @param {Boolean} oc: date offset correction | ||
* | ||
* oc(offset correction) is used when the object event is patched to google | ||
* event. We need apply one day to make compatibily between fullCalendar and | ||
* google. | ||
* | ||
*/ | ||
_string.content = function (str) { | ||
return str ? _string.escape(str) : ''; | ||
}; | ||
_string.date = function (v, a, oc) { | ||
// clone date | ||
var _v = new Date(v); | ||
if (a && oc) | ||
_v.setDate(_v.getDate() + 1); | ||
/** | ||
* date method | ||
* @param {Date} v: date object | ||
* @param {Boolean} a: all-day | ||
* @param {Boolean} oc: date offset correction | ||
* | ||
* oc(offset correction) is used when the object event is patched to google | ||
* event. We need apply one day to make compatibily between fullCalendar and | ||
* google. | ||
* | ||
*/ | ||
var date = JSON.stringify(_v).replace(/"/g, ''); | ||
return a ? date.substring(0, 10) : date; | ||
}; | ||
_string.date = function (v, a, oc) { | ||
// clone date | ||
var _v = new Date(v); | ||
if (a && oc) | ||
_v.setDate(_v.getDate() + 1); | ||
_string.dateTZID = function (v, tz) { | ||
var str = (JSON.stringify(v).replace(/[-, :,\.]/g, '')).substring(1, 16); | ||
return 'TZID=' + (tz ? (tz + ':' + str) : str); | ||
}; | ||
var date = JSON.stringify(_v).replace(/"/g, ''); | ||
return a ? date.substring(0, 10) : date; | ||
}; | ||
/** | ||
* value() method | ||
* return value date adding (or not) txt label | ||
*/ | ||
_string.dateTZID = function (v, tz) { | ||
var str = (JSON.stringify(v).replace(/[-, :,\.]/g, '')).substring(1, 16); | ||
return 'TZID=' + (tz ? (tz + ':' + str) : str); | ||
}; | ||
_string.value = function (d, noAddLabel) { | ||
var strDate = JSON.stringify(d).split('T')[0].replace(/[", -]/g, '') | ||
return !noAddLabel ? 'VALUE=DATE:' + strDate : strDate; | ||
}; | ||
/** | ||
* value() method | ||
* return value date adding (or not) txt label | ||
*/ | ||
// client-side: add caTools global var | ||
if (!serverSide) { | ||
if (typeof window.caTools == 'undefined') | ||
window.caTools = {}; | ||
window.caTools.Util = { date: _date, string: _string }; | ||
} | ||
})(typeof module != 'undefined' ? module : {}, typeof window != 'object'); | ||
_string.value = function (d, noAddLabel) { | ||
var strDate = JSON.stringify(d).split('T')[0].replace(/[", -]/g, '') | ||
return !noAddLabel ? 'VALUE=DATE:' + strDate : strDate; | ||
}; |
{ | ||
"name": "calendar-tools" | ||
, "version": "0.1.6" | ||
, "version": "0.1.7" | ||
, "description": "Calendar object model" | ||
@@ -5,0 +5,0 @@ , "keywords": ["calendar", "google calendar", "fullCalendar", "recurring events", "icalendar", "rfc2445"] |
@@ -70,2 +70,7 @@ # Calendar-tools | ||
### building client-side library | ||
you can use 'make build' rule to building client-side library. The generated | ||
file will be saved in dist/calendar-tools.js | ||
## License | ||
@@ -72,0 +77,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
488134
32
10039
99
0
4