jquery-week-calendar 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +17 -0
- data/lib/jquery-week-calendar.rb +11 -0
- data/lib/jquery-week-calendar/engine.rb +8 -0
- data/lib/jquery-week-calendar/generators.rb +24 -0
- data/lib/jquery-week-calendar/railtie.rb +11 -0
- data/vendor/assets/javascripts/jquery-week-calendar.js +3011 -0
- data/vendor/assets/stylesheets/jquery-week-calendar.css +278 -0
- metadata +89 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Adam Fortuna
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Wrapper for the jQuery-Week-Calendar Javascrip library.
|
2
|
+
|
3
|
+
https://github.com/themouette/jquery-week-calendar
|
4
|
+
|
5
|
+
Just add to your gemfile:
|
6
|
+
|
7
|
+
gem 'jquery-week-calendar'
|
8
|
+
|
9
|
+
And include in your application.js:
|
10
|
+
|
11
|
+
//= require jquery-week-calendar
|
12
|
+
|
13
|
+
Optionall include in your application.css
|
14
|
+
|
15
|
+
*= require jquery-week-calendar
|
16
|
+
|
17
|
+
You'll probably want to also use jquery-ui with it for a quick skin. For this I used the 'jquery-ui-themes' gem to get setup, but you can also use the Google hosted version of course.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module JqueryWeekCalendar
|
4
|
+
class Install < ::Rails::Generators::Base
|
5
|
+
JAVASCRIPTS = File.expand_path('../../../vendor/assets/javascripts', __FILE__)
|
6
|
+
STYLESHEETS = File.expand_path('../../../vendor/assets/stylesheets', __FILE__)
|
7
|
+
|
8
|
+
def self.source_root
|
9
|
+
@source_root ||= JAVASCRIPTS
|
10
|
+
end
|
11
|
+
|
12
|
+
def copy_calendar
|
13
|
+
Dir[File.join(JAVASCRIPTS, '*.js')].each do |file|
|
14
|
+
file = File.split(file).last
|
15
|
+
copy_file file, "public/javascripts/#{file}"
|
16
|
+
end
|
17
|
+
|
18
|
+
Dir[File.join(STYLESHEETS, '*.css')].each do |file|
|
19
|
+
file = File.split(file).last
|
20
|
+
copy_file file, "public/stylesheets/#{file}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,3011 @@
|
|
1
|
+
/**
|
2
|
+
* @version: 1.0 Alpha-1
|
3
|
+
* @author: Coolite Inc. http://www.coolite.com/
|
4
|
+
* @date: 2008-05-13
|
5
|
+
* @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
6
|
+
* @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
7
|
+
* @website: http://www.datejs.com/
|
8
|
+
*/
|
9
|
+
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|aft(er)?|from|hence)/i,subtract:/^(\-|bef(ore)?|ago)/i,yesterday:/^yes(terday)?/i,today:/^t(od(ay)?)?/i,tomorrow:/^tom(orrow)?/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^mn|min(ute)?s?/i,hour:/^h(our)?s?/i,week:/^w(eek)?s?/i,month:/^m(onth)?s?/i,day:/^d(ay)?s?/i,year:/^y(ear)?s?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a(?!u|p)|p)/i},timezones:[{name:"UTC",offset:"-000"},{name:"GMT",offset:"-000"},{name:"EST",offset:"-0500"},{name:"EDT",offset:"-0400"},{name:"CST",offset:"-0600"},{name:"CDT",offset:"-0500"},{name:"MST",offset:"-0700"},{name:"MDT",offset:"-0600"},{name:"PST",offset:"-0800"},{name:"PDT",offset:"-0700"}]};
|
10
|
+
(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,p=function(s,l){if(!l){l=2;}
|
11
|
+
return("000"+s).slice(l*-1);};$P.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};$P.setTimeToNow=function(){var n=new Date();this.setHours(n.getHours());this.setMinutes(n.getMinutes());this.setSeconds(n.getSeconds());this.setMilliseconds(n.getMilliseconds());return this;};$D.today=function(){return new Date().clearTime();};$D.compare=function(date1,date2){if(isNaN(date1)||isNaN(date2)){throw new Error(date1+" - "+date2);}else if(date1 instanceof Date&&date2 instanceof Date){return(date1<date2)?-1:(date1>date2)?1:0;}else{throw new TypeError(date1+" - "+date2);}};$D.equals=function(date1,date2){return(date1.compareTo(date2)===0);};$D.getDayNumberFromName=function(name){var n=$C.dayNames,m=$C.abbreviatedDayNames,o=$C.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s||o[i].toLowerCase()==s){return i;}}
|
12
|
+
return-1;};$D.getMonthNumberFromName=function(name){var n=$C.monthNames,m=$C.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
13
|
+
return-1;};$D.isLeapYear=function(year){return((year%4===0&&year%100!==0)||year%400===0);};$D.getDaysInMonth=function(year,month){return[31,($D.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};$D.getTimezoneAbbreviation=function(offset){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].offset===offset){return z[i].name;}}
|
14
|
+
return null;};$D.getTimezoneOffset=function(name){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].name===name.toUpperCase()){return z[i].offset;}}
|
15
|
+
return null;};$P.clone=function(){return new Date(this.getTime());};$P.compareTo=function(date){return Date.compare(this,date);};$P.equals=function(date){return Date.equals(this,date||new Date());};$P.between=function(start,end){return this.getTime()>=start.getTime()&&this.getTime()<=end.getTime();};$P.isAfter=function(date){return this.compareTo(date||new Date())===1;};$P.isBefore=function(date){return(this.compareTo(date||new Date())===-1);};$P.isToday=function(){return this.isSameDay(new Date());};$P.isSameDay=function(date){return this.clone().clearTime().equals(date.clone().clearTime());};$P.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};$P.addSeconds=function(value){return this.addMilliseconds(value*1000);};$P.addMinutes=function(value){return this.addMilliseconds(value*60000);};$P.addHours=function(value){return this.addMilliseconds(value*3600000);};$P.addDays=function(value){this.setDate(this.getDate()+value);return this;};$P.addWeeks=function(value){return this.addDays(value*7);};$P.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,$D.getDaysInMonth(this.getFullYear(),this.getMonth())));return this;};$P.addYears=function(value){return this.addMonths(value*12);};$P.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
|
16
|
+
var x=config;if(x.milliseconds){this.addMilliseconds(x.milliseconds);}
|
17
|
+
if(x.seconds){this.addSeconds(x.seconds);}
|
18
|
+
if(x.minutes){this.addMinutes(x.minutes);}
|
19
|
+
if(x.hours){this.addHours(x.hours);}
|
20
|
+
if(x.weeks){this.addWeeks(x.weeks);}
|
21
|
+
if(x.months){this.addMonths(x.months);}
|
22
|
+
if(x.years){this.addYears(x.years);}
|
23
|
+
if(x.days){this.addDays(x.days);}
|
24
|
+
return this;};var $y,$m,$d;$P.getWeek=function(){var a,b,c,d,e,f,g,n,s,w;$y=(!$y)?this.getFullYear():$y;$m=(!$m)?this.getMonth()+1:$m;$d=(!$d)?this.getDate():$d;if($m<=2){a=$y-1;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=0;f=$d-1+(31*($m-1));}else{a=$y;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=s+1;f=$d+((153*($m-3)+2)/5)+58+s;}
|
25
|
+
g=(a+b)%7;d=(f+g-e)%7;n=(f+3-d)|0;if(n<0){w=53-((g-s)/5|0);}else if(n>364+s){w=1;}else{w=(n/7|0)+1;}
|
26
|
+
$y=$m=$d=null;return w;};$P.getISOWeek=function(){$y=this.getUTCFullYear();$m=this.getUTCMonth()+1;$d=this.getUTCDate();return p(this.getWeek());};$P.setWeek=function(n){return this.moveToDayOfWeek(1).addWeeks(n-this.getWeek());};$D._validate=function(n,min,max,name){if(typeof n=="undefined"){return false;}else if(typeof n!="number"){throw new TypeError(n+" is not a Number.");}else if(n<min||n>max){throw new RangeError(n+" is not a valid value for "+name+".");}
|
27
|
+
return true;};$D.validateMillisecond=function(value){return $D._validate(value,0,999,"millisecond");};$D.validateSecond=function(value){return $D._validate(value,0,59,"second");};$D.validateMinute=function(value){return $D._validate(value,0,59,"minute");};$D.validateHour=function(value){return $D._validate(value,0,23,"hour");};$D.validateDay=function(value,year,month){return $D._validate(value,1,$D.getDaysInMonth(year,month),"day");};$D.validateMonth=function(value){return $D._validate(value,0,11,"month");};$D.validateYear=function(value){return $D._validate(value,0,9999,"year");};$P.set=function(config){if($D.validateMillisecond(config.millisecond)){this.addMilliseconds(config.millisecond-this.getMilliseconds());}
|
28
|
+
if($D.validateSecond(config.second)){this.addSeconds(config.second-this.getSeconds());}
|
29
|
+
if($D.validateMinute(config.minute)){this.addMinutes(config.minute-this.getMinutes());}
|
30
|
+
if($D.validateHour(config.hour)){this.addHours(config.hour-this.getHours());}
|
31
|
+
if($D.validateMonth(config.month)){this.addMonths(config.month-this.getMonth());}
|
32
|
+
if($D.validateYear(config.year)){this.addYears(config.year-this.getFullYear());}
|
33
|
+
if($D.validateDay(config.day,this.getFullYear(),this.getMonth())){this.addDays(config.day-this.getDate());}
|
34
|
+
if(config.timezone){this.setTimezone(config.timezone);}
|
35
|
+
if(config.timezoneOffset){this.setTimezoneOffset(config.timezoneOffset);}
|
36
|
+
if(config.week&&$D._validate(config.week,0,53,"week")){this.setWeek(config.week);}
|
37
|
+
return this;};$P.moveToFirstDayOfMonth=function(){return this.set({day:1});};$P.moveToLastDayOfMonth=function(){return this.set({day:$D.getDaysInMonth(this.getFullYear(),this.getMonth())});};$P.moveToNthOccurrence=function(dayOfWeek,occurrence){var shift=0;if(occurrence>0){shift=occurrence-1;}
|
38
|
+
else if(occurrence===-1){this.moveToLastDayOfMonth();if(this.getDay()!==dayOfWeek){this.moveToDayOfWeek(dayOfWeek,-1);}
|
39
|
+
return this;}
|
40
|
+
return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek,+1).addWeeks(shift);};$P.moveToDayOfWeek=function(dayOfWeek,orient){var diff=(dayOfWeek-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};$P.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};$P.getOrdinalNumber=function(){return Math.ceil((this.clone().clearTime()-new Date(this.getFullYear(),0,1))/86400000)+1;};$P.getTimezone=function(){return $D.getTimezoneAbbreviation(this.getUTCOffset());};$P.setTimezoneOffset=function(offset){var here=this.getTimezoneOffset(),there=Number(offset)*-6/10;return this.addMinutes(there-here);};$P.setTimezone=function(offset){return this.setTimezoneOffset($D.getTimezoneOffset(offset));};$P.hasDaylightSavingTime=function(){return(Date.today().set({month:0,day:1}).getTimezoneOffset()!==Date.today().set({month:6,day:1}).getTimezoneOffset());};$P.isDaylightSavingTime=function(){return(this.hasDaylightSavingTime()&&new Date().getTimezoneOffset()===Date.today().set({month:6,day:1}).getTimezoneOffset());};$P.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r.charAt(0)+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};$P.getElapsed=function(date){return(date||new Date())-this;};if(!$P.toISOString){$P.toISOString=function(){function f(n){return n<10?'0'+n:n;}
|
41
|
+
return'"'+this.getUTCFullYear()+'-'+
|
42
|
+
f(this.getUTCMonth()+1)+'-'+
|
43
|
+
f(this.getUTCDate())+'T'+
|
44
|
+
f(this.getUTCHours())+':'+
|
45
|
+
f(this.getUTCMinutes())+':'+
|
46
|
+
f(this.getUTCSeconds())+'Z"';};}
|
47
|
+
$P._toString=$P.toString;$P.toString=function(format){var x=this;if(format&&format.length==1){var c=$C.formatPatterns;x.t=x.toString;switch(format){case"d":return x.t(c.shortDate);case"D":return x.t(c.longDate);case"F":return x.t(c.fullDateTime);case"m":return x.t(c.monthDay);case"r":return x.t(c.rfc1123);case"s":return x.t(c.sortableDateTime);case"t":return x.t(c.shortTime);case"T":return x.t(c.longTime);case"u":return x.t(c.universalSortableDateTime);case"y":return x.t(c.yearMonth);}}
|
48
|
+
var ord=function(n){switch(n*1){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};return format?format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g,function(m){if(m.charAt(0)==="\\"){return m.replace("\\","");}
|
49
|
+
x.h=x.getHours;switch(m){case"hh":return p(x.h()<13?(x.h()===0?12:x.h()):(x.h()-12));case"h":return x.h()<13?(x.h()===0?12:x.h()):(x.h()-12);case"HH":return p(x.h());case"H":return x.h();case"mm":return p(x.getMinutes());case"m":return x.getMinutes();case"ss":return p(x.getSeconds());case"s":return x.getSeconds();case"yyyy":return p(x.getFullYear(),4);case"yy":return p(x.getFullYear());case"dddd":return $C.dayNames[x.getDay()];case"ddd":return $C.abbreviatedDayNames[x.getDay()];case"dd":return p(x.getDate());case"d":return x.getDate();case"MMMM":return $C.monthNames[x.getMonth()];case"MMM":return $C.abbreviatedMonthNames[x.getMonth()];case"MM":return p((x.getMonth()+1));case"M":return x.getMonth()+1;case"t":return x.h()<12?$C.amDesignator.substring(0,1):$C.pmDesignator.substring(0,1);case"tt":return x.h()<12?$C.amDesignator:$C.pmDesignator;case"S":return ord(x.getDate());default:return m;}}):this._toString();};}());
|
50
|
+
(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,$N=Number.prototype;$P._orient=+1;$P._nth=null;$P._is=false;$P._same=false;$P._isSecond=false;$N._dateElement="day";$P.next=function(){this._orient=+1;return this;};$D.next=function(){return $D.today().next();};$P.last=$P.prev=$P.previous=function(){this._orient=-1;return this;};$D.last=$D.prev=$D.previous=function(){return $D.today().last();};$P.is=function(){this._is=true;return this;};$P.same=function(){this._same=true;this._isSecond=false;return this;};$P.today=function(){return this.same().day();};$P.weekday=function(){if(this._is){this._is=false;return(!this.is().sat()&&!this.is().sun());}
|
51
|
+
return false;};$P.at=function(time){return(typeof time==="string")?$D.parse(this.toString("d")+" "+time):this.set(time);};$N.fromNow=$N.after=function(date){var c={};c[this._dateElement]=this;return((!date)?new Date():date.clone()).add(c);};$N.ago=$N.before=function(date){var c={};c[this._dateElement]=this*-1;return((!date)?new Date():date.clone()).add(c);};var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),pxf=("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),nth=("final first second third fourth fifth").split(/\s/),de;$P.toObject=function(){var o={};for(var i=0;i<px.length;i++){o[px[i].toLowerCase()]=this["get"+pxf[i]]();}
|
52
|
+
return o;};$D.fromObject=function(config){config.week=null;return Date.today().set(config);};var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
|
53
|
+
if(this._nth!==null){if(this._isSecond){this.addSeconds(this._orient*-1);}
|
54
|
+
this._isSecond=false;var ntemp=this._nth;this._nth=null;var temp=this.clone().moveToLastDayOfMonth();this.moveToNthOccurrence(n,ntemp);if(this>temp){throw new RangeError($D.getDayName(n)+" does not occur "+ntemp+" times in the month of "+$D.getMonthName(temp.getMonth())+" "+temp.getFullYear()+".");}
|
55
|
+
return this;}
|
56
|
+
return this.moveToDayOfWeek(n,this._orient);};};var sdf=function(n){return function(){var t=$D.today(),shift=n-t.getDay();if(n===0&&$C.firstDayOfWeek===1&&t.getDay()!==0){shift=shift+7;}
|
57
|
+
return t.addDays(shift);};};for(var i=0;i<dx.length;i++){$D[dx[i].toUpperCase()]=$D[dx[i].toUpperCase().substring(0,3)]=i;$D[dx[i]]=$D[dx[i].substring(0,3)]=sdf(i);$P[dx[i]]=$P[dx[i].substring(0,3)]=df(i);}
|
58
|
+
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
|
59
|
+
return this.moveToMonth(n,this._orient);};};var smf=function(n){return function(){return $D.today().set({month:n,day:1});};};for(var j=0;j<mx.length;j++){$D[mx[j].toUpperCase()]=$D[mx[j].toUpperCase().substring(0,3)]=j;$D[mx[j]]=$D[mx[j].substring(0,3)]=smf(j);$P[mx[j]]=$P[mx[j].substring(0,3)]=mf(j);}
|
60
|
+
var ef=function(j){return function(){if(this._isSecond){this._isSecond=false;return this;}
|
61
|
+
if(this._same){this._same=this._is=false;var o1=this.toObject(),o2=(arguments[0]||new Date()).toObject(),v="",k=j.toLowerCase();for(var m=(px.length-1);m>-1;m--){v=px[m].toLowerCase();if(o1[v]!=o2[v]){return false;}
|
62
|
+
if(k==v){break;}}
|
63
|
+
return true;}
|
64
|
+
if(j.substring(j.length-1)!="s"){j+="s";}
|
65
|
+
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$P[de]=$P[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}
|
66
|
+
$P._ss=ef("Second");var nthfn=function(n){return function(dayOfWeek){if(this._same){return this._ss(arguments[0]);}
|
67
|
+
if(dayOfWeek||dayOfWeek===0){return this.moveToNthOccurrence(dayOfWeek,n);}
|
68
|
+
this._nth=n;if(n===2&&(dayOfWeek===undefined||dayOfWeek===null)){this._isSecond=true;return this.addSeconds(this._orient);}
|
69
|
+
return this;};};for(var l=0;l<nth.length;l++){$P[nth[l]]=(l===0)?nthfn(-1):nthfn(l);}}());
|
70
|
+
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
|
71
|
+
break;}
|
72
|
+
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
|
73
|
+
rx.push(r[0]);s=r[1];}
|
74
|
+
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
|
75
|
+
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
|
76
|
+
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
|
77
|
+
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
|
78
|
+
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
79
|
+
try{r=(px[i].call(this,s));}catch(e){r=null;}
|
80
|
+
if(r){return r;}}
|
81
|
+
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
82
|
+
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
|
83
|
+
rx.push(r[0]);s=r[1];}
|
84
|
+
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
|
85
|
+
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
|
86
|
+
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
|
87
|
+
s=q[1];}
|
88
|
+
if(!r){throw new $P.Exception(s);}
|
89
|
+
if(q){throw new $P.Exception(q[1]);}
|
90
|
+
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
|
91
|
+
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
|
92
|
+
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
|
93
|
+
if(!last&&q[1].length===0){last=true;}
|
94
|
+
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
|
95
|
+
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
|
96
|
+
if(rx[1].length<best[1].length){best=rx;}
|
97
|
+
if(best[1].length===0){break;}}
|
98
|
+
if(best[0].length===0){return best;}
|
99
|
+
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
|
100
|
+
best[1]=q[1];}
|
101
|
+
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
|
102
|
+
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
|
103
|
+
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
|
104
|
+
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo;var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
|
105
|
+
return rx;};$D.Grammar={};$D.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=(s.length==3)?"jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4:Number(s)-1;};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<$C.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
|
106
|
+
var now=new Date();if((this.hour||this.minute)&&(!this.month&&!this.year&&!this.day)){this.day=now.getDate();}
|
107
|
+
if(!this.year){this.year=now.getFullYear();}
|
108
|
+
if(!this.month&&this.month!==0){this.month=now.getMonth();}
|
109
|
+
if(!this.day){this.day=1;}
|
110
|
+
if(!this.hour){this.hour=0;}
|
111
|
+
if(!this.minute){this.minute=0;}
|
112
|
+
if(!this.second){this.second=0;}
|
113
|
+
if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else if(this.meridian=="a"&&this.hour==12){this.hour=0;}}
|
114
|
+
if(this.day>$D.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
|
115
|
+
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
|
116
|
+
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
|
117
|
+
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
|
118
|
+
var today=$D.today();if(this.now&&!this.unit&&!this.operator){return new Date();}else if(this.now){today=new Date();}
|
119
|
+
var expression=!!(this.days&&this.days!==null||this.orient||this.operator);var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(!this.now&&"hour minute second".indexOf(this.unit)!=-1){today.setTimeToNow();}
|
120
|
+
if(this.month||this.month===0){if("year day hour minute second".indexOf(this.unit)!=-1){this.value=this.month+1;this.month=null;expression=true;}}
|
121
|
+
if(!expression&&this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(!this.month){this.month=temp.getMonth();}
|
122
|
+
this.year=temp.getFullYear();}
|
123
|
+
if(expression&&this.weekday&&this.unit!="month"){this.unit="day";gap=($D.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
|
124
|
+
if(this.month&&this.unit=="day"&&this.operator){this.value=(this.month+1);this.month=null;}
|
125
|
+
if(this.value!=null&&this.month!=null&&this.year!=null){this.day=this.value*1;}
|
126
|
+
if(this.month&&!this.day&&this.value){today.set({day:this.value*1});if(!expression){this.day=this.value*1;}}
|
127
|
+
if(!this.month&&this.value&&this.unit=="month"&&!this.now){this.month=this.value;expression=true;}
|
128
|
+
if(expression&&(this.month||this.month===0)&&this.unit!="year"){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
|
129
|
+
if(!this.unit){this.unit="day";}
|
130
|
+
if(!this.value&&this.operator&&this.operator!==null&&this[this.unit+"s"]&&this[this.unit+"s"]!==null){this[this.unit+"s"]=this[this.unit+"s"]+((this.operator=="add")?1:-1)+(this.value||0)*orient;}else if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
|
131
|
+
this[this.unit+"s"]=this.value*orient;}
|
132
|
+
if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else if(this.meridian=="a"&&this.hour==12){this.hour=0;}}
|
133
|
+
if(this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(temp.getMonth()!==today.getMonth()){this.month=temp.getMonth();}}
|
134
|
+
if((this.month||this.month===0)&&!this.day){this.day=1;}
|
135
|
+
if(!this.orient&&!this.operator&&this.unit=="week"&&this.value&&!this.day&&!this.month){return Date.today().setWeek(this.value);}
|
136
|
+
if(expression&&this.timezone&&this.day&&this.days){this.day=this.days;}
|
137
|
+
return(expression)?today.add(this):today.set(this);}};var _=$D.Parsing.Operators,g=$D.Grammar,t=$D.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|@|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=$C.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
|
138
|
+
fn=_C[keys]=_.any.apply(null,px);}
|
139
|
+
return fn;};g.ctoken2=function(key){return _.rtoken($C.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.m,g.s],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("second minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[$C.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw $D.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
|
140
|
+
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["\"yyyy-MM-ddTHH:mm:ssZ\"","yyyy-MM-ddTHH:mm:ssZ","yyyy-MM-ddTHH:mm:ssz","yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mmZ","yyyy-MM-ddTHH:mmz","yyyy-MM-ddTHH:mm","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","MMddyyyy","ddMMyyyy","Mddyyyy","ddMyyyy","Mdyyyy","dMyyyy","yyyy","Mdyy","dMyy","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
|
141
|
+
return g._start.call({},s);};$D._parse=$D.parse;$D.parse=function(s){var r=null;if(!s){return null;}
|
142
|
+
if(s instanceof Date){return s;}
|
143
|
+
try{r=$D.Grammar.start.call({},s.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));}catch(e){return null;}
|
144
|
+
return((r[1].length===0)?r[0]:null);};$D.getParseFunction=function(fx){var fn=$D.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
145
|
+
return((r[1].length===0)?r[0]:null);};};$D.parseExact=function(s,fx){return $D.getParseFunction(fx)(s);};}());
|
146
|
+
|
147
|
+
|
148
|
+
/*
|
149
|
+
* jQuery.weekCalendar v2.0-dev
|
150
|
+
*
|
151
|
+
* for support join us at the google group:
|
152
|
+
* - http://groups.google.com/group/jquery-week-calendar
|
153
|
+
* have a look to the wiki for documentation:
|
154
|
+
* - http://wiki.github.com/themouette/jquery-week-calendar/
|
155
|
+
* something went bad ? report an issue:
|
156
|
+
* - http://github.com/themouette/jquery-week-calendar/issues
|
157
|
+
* get the last version on github:
|
158
|
+
* - http://github.com/themouette/jquery-week-calendar
|
159
|
+
*
|
160
|
+
* Copyright (c) 2009 Rob Monie
|
161
|
+
* Copyright (c) 2010 Julien MUETTON
|
162
|
+
* Dual licensed under the MIT and GPL licenses:
|
163
|
+
* http://www.opensource.org/licenses/mit-license.php
|
164
|
+
* http://www.gnu.org/licenses/gpl.html
|
165
|
+
*
|
166
|
+
* If you're after a monthly calendar plugin, check out this one :
|
167
|
+
* http://arshaw.com/fullcalendar/
|
168
|
+
*/
|
169
|
+
|
170
|
+
(function($) {
|
171
|
+
// check the jquery version
|
172
|
+
var _v = $.fn.jquery.split('.'),
|
173
|
+
_jQuery14OrLower = (10 * _v[0] + _v[1]) < 15;
|
174
|
+
|
175
|
+
$.widget('ui.weekCalendar', (function() {
|
176
|
+
var _currentAjaxCall;
|
177
|
+
return {
|
178
|
+
options: {
|
179
|
+
date: new Date(),
|
180
|
+
timeFormat: null,
|
181
|
+
dateFormat: 'M d, Y',
|
182
|
+
alwaysDisplayTimeMinutes: true,
|
183
|
+
use24Hour: false,
|
184
|
+
daysToShow: 7,
|
185
|
+
minBodyHeight: 100,
|
186
|
+
firstDayOfWeek: function(calendar) {
|
187
|
+
if ($(calendar).weekCalendar('option', 'daysToShow') != 5) {
|
188
|
+
return 0;
|
189
|
+
} else {
|
190
|
+
//workweek
|
191
|
+
return 1;
|
192
|
+
}
|
193
|
+
}, // 0 = Sunday, 1 = Monday, 2 = Tuesday, ... , 6 = Saturday
|
194
|
+
useShortDayNames: false,
|
195
|
+
timeSeparator: ' to ',
|
196
|
+
startParam: 'start',
|
197
|
+
endParam: 'end',
|
198
|
+
businessHours: {start: 8, end: 18, limitDisplay: false},
|
199
|
+
newEventText: 'New Event',
|
200
|
+
timeslotHeight: 20,
|
201
|
+
defaultEventLength: 2,
|
202
|
+
timeslotsPerHour: 4,
|
203
|
+
minDate: null,
|
204
|
+
maxDate: null,
|
205
|
+
buttons: true,
|
206
|
+
buttonText: {
|
207
|
+
today: 'today',
|
208
|
+
lastWeek: 'previous',
|
209
|
+
nextWeek: 'next'
|
210
|
+
},
|
211
|
+
switchDisplay: {},
|
212
|
+
scrollToHourMillis: 500,
|
213
|
+
allowEventDelete: false,
|
214
|
+
allowCalEventOverlap: false,
|
215
|
+
overlapEventsSeparate: false,
|
216
|
+
totalEventsWidthPercentInOneColumn : 100,
|
217
|
+
readonly: false,
|
218
|
+
allowEventCreation: true,
|
219
|
+
deletable: function(calEvent, element) {
|
220
|
+
return true;
|
221
|
+
},
|
222
|
+
draggable: function(calEvent, element) {
|
223
|
+
return true;
|
224
|
+
},
|
225
|
+
resizable: function(calEvent, element) {
|
226
|
+
return true;
|
227
|
+
},
|
228
|
+
eventClick: function(calEvent, element, dayFreeBusyManager,
|
229
|
+
calendar, clickEvent) {
|
230
|
+
},
|
231
|
+
eventRender: function(calEvent, element) {
|
232
|
+
return element;
|
233
|
+
},
|
234
|
+
eventAfterRender: function(calEvent, element) {
|
235
|
+
return element;
|
236
|
+
},
|
237
|
+
eventRefresh: function(calEvent, element) {
|
238
|
+
return element;
|
239
|
+
},
|
240
|
+
eventDrag: function(calEvent, element) {
|
241
|
+
},
|
242
|
+
eventDrop: function(calEvent, element) {
|
243
|
+
},
|
244
|
+
eventResize: function(calEvent, element) {
|
245
|
+
},
|
246
|
+
eventNew: function(calEvent, element, dayFreeBusyManager,
|
247
|
+
calendar, mouseupEvent) {
|
248
|
+
},
|
249
|
+
eventMouseover: function(calEvent, $event) {
|
250
|
+
},
|
251
|
+
eventMouseout: function(calEvent, $event) {
|
252
|
+
},
|
253
|
+
eventDelete: function(calEvent, element, dayFreeBusyManager,
|
254
|
+
calendar, clickEvent) {
|
255
|
+
calendar.weekCalendar('removeEvent',calEvent.id);
|
256
|
+
},
|
257
|
+
calendarBeforeLoad: function(calendar) {
|
258
|
+
},
|
259
|
+
calendarAfterLoad: function(calendar) {
|
260
|
+
},
|
261
|
+
noEvents: function() {
|
262
|
+
},
|
263
|
+
eventHeader: function(calEvent, calendar) {
|
264
|
+
var options = calendar.weekCalendar('option');
|
265
|
+
var one_hour = 3600000;
|
266
|
+
var displayTitleWithTime = calEvent.end.getTime() - calEvent.start.getTime() <= (one_hour / options.timeslotsPerHour);
|
267
|
+
if (displayTitleWithTime) {
|
268
|
+
return calendar.weekCalendar(
|
269
|
+
'formatTime', calEvent.start) +
|
270
|
+
': ' + calEvent.title;
|
271
|
+
} else {
|
272
|
+
return calendar.weekCalendar(
|
273
|
+
'formatTime', calEvent.start) +
|
274
|
+
options.timeSeparator +
|
275
|
+
calendar.weekCalendar(
|
276
|
+
'formatTime', calEvent.end);
|
277
|
+
}
|
278
|
+
},
|
279
|
+
eventBody: function(calEvent, calendar) {
|
280
|
+
return calEvent.title;
|
281
|
+
},
|
282
|
+
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
283
|
+
longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
284
|
+
shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
285
|
+
longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
286
|
+
/* multi-users options */
|
287
|
+
/**
|
288
|
+
* the available users for calendar.
|
289
|
+
* if you want to display users separately, enable the
|
290
|
+
* showAsSeparateUsers option.
|
291
|
+
* if you provide a list of user and do not enable showAsSeparateUsers
|
292
|
+
* option, then only the events that belongs to one or several of
|
293
|
+
* given users will be displayed
|
294
|
+
* @type {array}
|
295
|
+
*/
|
296
|
+
users: [],
|
297
|
+
/**
|
298
|
+
* should the calendar be displayed with separate column for each
|
299
|
+
* users.
|
300
|
+
* note that this option does nothing if you do not provide at least
|
301
|
+
* one user.
|
302
|
+
* @type {boolean}
|
303
|
+
*/
|
304
|
+
showAsSeparateUsers: true,
|
305
|
+
/**
|
306
|
+
* callback used to read user id from a user object.
|
307
|
+
* @param {Object} user the user to retrieve the id from.
|
308
|
+
* @param {number} index the user index from user list.
|
309
|
+
* @param {jQuery} calendar the calendar object.
|
310
|
+
* @return {int|String} the user id.
|
311
|
+
*/
|
312
|
+
getUserId: function(user, index, calendar) {
|
313
|
+
return index;
|
314
|
+
},
|
315
|
+
/**
|
316
|
+
* callback used to read user name from a user object.
|
317
|
+
* @param {Object} user the user to retrieve the name from.
|
318
|
+
* @param {number} index the user index from user list.
|
319
|
+
* @param {jQuery} calendar the calendar object.
|
320
|
+
* @return {String} the user name.
|
321
|
+
*/
|
322
|
+
getUserName: function(user, index, calendar) {
|
323
|
+
return user;
|
324
|
+
},
|
325
|
+
/**
|
326
|
+
* reads the id(s) of user(s) for who the event should be displayed.
|
327
|
+
* @param {Object} calEvent the calEvent to read informations from.
|
328
|
+
* @param {jQuery} calendar the calendar object.
|
329
|
+
* @return {number|String|Array} the user id(s) to appened events for.
|
330
|
+
*/
|
331
|
+
getEventUserId: function(calEvent, calendar) {
|
332
|
+
return calEvent.userId;
|
333
|
+
},
|
334
|
+
/**
|
335
|
+
* sets user id(s) to the calEvent
|
336
|
+
* @param {Object} calEvent the calEvent to set informations to.
|
337
|
+
* @param {jQuery} calendar the calendar object.
|
338
|
+
* @return {Object} the calEvent with modified user id.
|
339
|
+
*/
|
340
|
+
setEventUserId: function(userId, calEvent, calendar) {
|
341
|
+
calEvent.userId = userId;
|
342
|
+
return calEvent;
|
343
|
+
},
|
344
|
+
/* freeBusy options */
|
345
|
+
/**
|
346
|
+
* should the calendar display freebusys ?
|
347
|
+
* @type {boolean}
|
348
|
+
*/
|
349
|
+
displayFreeBusys: false,
|
350
|
+
/**
|
351
|
+
* read the id(s) for who the freebusy is available
|
352
|
+
* @param {Object} calEvent the calEvent to read informations from.
|
353
|
+
* @param {jQuery} calendar the calendar object.
|
354
|
+
* @return {number|String|Array} the user id(s) to appened events for.
|
355
|
+
*/
|
356
|
+
getFreeBusyUserId: function(calFreeBusy, calendar) {
|
357
|
+
return calFreeBusy.userId;
|
358
|
+
},
|
359
|
+
/**
|
360
|
+
* the default freeBusy object, used to manage default state
|
361
|
+
* @type {Object}
|
362
|
+
*/
|
363
|
+
defaultFreeBusy: {free: false},
|
364
|
+
/**
|
365
|
+
* function used to display the freeBusy element
|
366
|
+
* @type {Function}
|
367
|
+
* @param {Object} freeBusy the freeBusy timeslot to render.
|
368
|
+
* @param {jQuery} $freeBusy the freeBusy HTML element.
|
369
|
+
* @param {jQuery} calendar the calendar element.
|
370
|
+
*/
|
371
|
+
freeBusyRender: function(freeBusy, $freeBusy, calendar) {
|
372
|
+
if (!freeBusy.free) {
|
373
|
+
$freeBusy.addClass('free-busy-busy');
|
374
|
+
}
|
375
|
+
else {
|
376
|
+
$freeBusy.addClass('free-busy-free');
|
377
|
+
}
|
378
|
+
return $freeBusy;
|
379
|
+
},
|
380
|
+
/* other options */
|
381
|
+
/**
|
382
|
+
* true means start on first day of week, false means starts on
|
383
|
+
* startDate.
|
384
|
+
* @param {jQuery} calendar the calendar object.
|
385
|
+
* @type {Function|bool}
|
386
|
+
*/
|
387
|
+
startOnFirstDayOfWeek: function(calendar) {
|
388
|
+
return $(calendar).weekCalendar('option', 'daysToShow') >= 5;
|
389
|
+
},
|
390
|
+
/**
|
391
|
+
* should the columns be rendered alternatively using odd/even
|
392
|
+
* class
|
393
|
+
* @type {boolean}
|
394
|
+
*/
|
395
|
+
displayOddEven: false,
|
396
|
+
textSize: 13,
|
397
|
+
/**
|
398
|
+
* the title attribute for the calendar. possible placeholders are:
|
399
|
+
* <ul>
|
400
|
+
* <li>%start%</li>
|
401
|
+
* <li>%end%</li>
|
402
|
+
* <li>%date%</li>
|
403
|
+
* </ul>
|
404
|
+
* @type {Function|string}
|
405
|
+
* @param {number} option daysToShow.
|
406
|
+
* @return {String} the title attribute for the calendar.
|
407
|
+
*/
|
408
|
+
title: '%start% - %end%',
|
409
|
+
/**
|
410
|
+
* default options to pass to callback
|
411
|
+
* you can pass a function returning an object or a litteral object
|
412
|
+
* @type {object|function(#calendar)}
|
413
|
+
*/
|
414
|
+
jsonOptions: {},
|
415
|
+
headerSeparator: '<br />',
|
416
|
+
/**
|
417
|
+
* returns formatted header for day display
|
418
|
+
* @type {function(date,calendar)}
|
419
|
+
*/
|
420
|
+
getHeaderDate: null,
|
421
|
+
preventDragOnEventCreation: false,
|
422
|
+
/**
|
423
|
+
* the event on which to bind calendar resize
|
424
|
+
* @type {string}
|
425
|
+
*/
|
426
|
+
resizeEvent: 'resize.weekcalendar'
|
427
|
+
},
|
428
|
+
|
429
|
+
/***********************
|
430
|
+
* Initialise calendar *
|
431
|
+
***********************/
|
432
|
+
_create: function() {
|
433
|
+
var self = this;
|
434
|
+
self._computeOptions();
|
435
|
+
self._setupEventDelegation();
|
436
|
+
self._renderCalendar();
|
437
|
+
self._loadCalEvents();
|
438
|
+
self._resizeCalendar();
|
439
|
+
self._scrollToHour(self.options.date.getHours(), true);
|
440
|
+
|
441
|
+
if (this.options.resizeEvent) {
|
442
|
+
$(window).unbind(this.options.resizeEvent);
|
443
|
+
$(window).bind(this.options.resizeEvent, function() {
|
444
|
+
self._resizeCalendar();
|
445
|
+
});
|
446
|
+
}
|
447
|
+
|
448
|
+
},
|
449
|
+
|
450
|
+
/********************
|
451
|
+
* public functions *
|
452
|
+
********************/
|
453
|
+
/*
|
454
|
+
* Refresh the events for the currently displayed week.
|
455
|
+
*/
|
456
|
+
refresh: function() {
|
457
|
+
//reload with existing week
|
458
|
+
this._loadCalEvents(this.element.data('startDate'));
|
459
|
+
},
|
460
|
+
|
461
|
+
/*
|
462
|
+
* Clear all events currently loaded into the calendar
|
463
|
+
*/
|
464
|
+
clear: function() {
|
465
|
+
this._clearCalendar();
|
466
|
+
},
|
467
|
+
|
468
|
+
/*
|
469
|
+
* Go to this week
|
470
|
+
*/
|
471
|
+
today: function() {
|
472
|
+
this._clearCalendar();
|
473
|
+
this._loadCalEvents(new Date());
|
474
|
+
},
|
475
|
+
|
476
|
+
/*
|
477
|
+
* Go to the previous week relative to the currently displayed week
|
478
|
+
*/
|
479
|
+
prevWeek: function() {
|
480
|
+
//minus more than 1 day to be sure we're in previous week - account for daylight savings or other anomolies
|
481
|
+
var newDate = new Date(this.element.data('startDate').getTime() - (MILLIS_IN_WEEK / 6));
|
482
|
+
this._clearCalendar();
|
483
|
+
this._loadCalEvents(newDate);
|
484
|
+
},
|
485
|
+
|
486
|
+
/*
|
487
|
+
* Go to the next week relative to the currently displayed week
|
488
|
+
*/
|
489
|
+
nextWeek: function() {
|
490
|
+
//add 8 days to be sure of being in prev week - allows for daylight savings or other anomolies
|
491
|
+
var newDate = new Date(this.element.data('startDate').getTime() + MILLIS_IN_WEEK + MILLIS_IN_DAY);
|
492
|
+
this._clearCalendar();
|
493
|
+
this._loadCalEvents(newDate);
|
494
|
+
},
|
495
|
+
|
496
|
+
/*
|
497
|
+
* Reload the calendar to whatever week the date passed in falls on.
|
498
|
+
*/
|
499
|
+
gotoWeek: function(date) {
|
500
|
+
this._clearCalendar();
|
501
|
+
this._loadCalEvents(date);
|
502
|
+
},
|
503
|
+
|
504
|
+
/*
|
505
|
+
* Reload the calendar to whatever week the date passed in falls on.
|
506
|
+
*/
|
507
|
+
gotoDate: function(date) {
|
508
|
+
this._clearCalendar();
|
509
|
+
this._loadCalEvents(date);
|
510
|
+
},
|
511
|
+
|
512
|
+
/**
|
513
|
+
* change the number of days to show
|
514
|
+
*/
|
515
|
+
setDaysToShow: function(daysToShow) {
|
516
|
+
var self = this;
|
517
|
+
var hour = self._getCurrentScrollHour();
|
518
|
+
self.options.daysToShow = daysToShow;
|
519
|
+
$(self.element).html('');
|
520
|
+
self._renderCalendar();
|
521
|
+
self._loadCalEvents();
|
522
|
+
self._resizeCalendar();
|
523
|
+
self._scrollToHour(hour, false);
|
524
|
+
|
525
|
+
if (this.options.resizeEvent) {
|
526
|
+
$(window).unbind(this.options.resizeEvent);
|
527
|
+
$(window).bind(this.options.resizeEvent, function() {
|
528
|
+
self._resizeCalendar();
|
529
|
+
});
|
530
|
+
}
|
531
|
+
},
|
532
|
+
|
533
|
+
/*
|
534
|
+
* Remove an event based on it's id
|
535
|
+
*/
|
536
|
+
removeEvent: function(eventId) {
|
537
|
+
|
538
|
+
var self = this;
|
539
|
+
|
540
|
+
self.element.find('.wc-cal-event').each(function() {
|
541
|
+
if ($(this).data('calEvent').id === eventId) {
|
542
|
+
$(this).remove();
|
543
|
+
return false;
|
544
|
+
}
|
545
|
+
});
|
546
|
+
|
547
|
+
//this could be more efficient rather than running on all days regardless...
|
548
|
+
self.element.find('.wc-day-column-inner').each(function() {
|
549
|
+
self._adjustOverlappingEvents($(this));
|
550
|
+
});
|
551
|
+
},
|
552
|
+
|
553
|
+
/*
|
554
|
+
* Removes any events that have been added but not yet saved (have no id).
|
555
|
+
* This is useful to call after adding a freshly saved new event.
|
556
|
+
*/
|
557
|
+
removeUnsavedEvents: function() {
|
558
|
+
|
559
|
+
var self = this;
|
560
|
+
|
561
|
+
self.element.find('.wc-new-cal-event').each(function() {
|
562
|
+
$(this).remove();
|
563
|
+
});
|
564
|
+
|
565
|
+
//this could be more efficient rather than running on all days regardless...
|
566
|
+
self.element.find('.wc-day-column-inner').each(function() {
|
567
|
+
self._adjustOverlappingEvents($(this));
|
568
|
+
});
|
569
|
+
},
|
570
|
+
|
571
|
+
/*
|
572
|
+
* update an event in the calendar. If the event exists it refreshes
|
573
|
+
* it's rendering. If it's a new event that does not exist in the calendar
|
574
|
+
* it will be added.
|
575
|
+
*/
|
576
|
+
updateEvent: function(calEvent) {
|
577
|
+
this._updateEventInCalendar(calEvent);
|
578
|
+
},
|
579
|
+
|
580
|
+
/*
|
581
|
+
* Returns an array of timeslot start and end times based on
|
582
|
+
* the configured grid of the calendar. Returns in both date and
|
583
|
+
* formatted time based on the 'timeFormat' config option.
|
584
|
+
*/
|
585
|
+
getTimeslotTimes: function(date) {
|
586
|
+
var options = this.options;
|
587
|
+
var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
|
588
|
+
var startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), firstHourDisplayed);
|
589
|
+
|
590
|
+
var times = [],
|
591
|
+
startMillis = startDate.getTime();
|
592
|
+
for (var i = 0; i < options.timeslotsPerDay; i++) {
|
593
|
+
var endMillis = startMillis + options.millisPerTimeslot;
|
594
|
+
times[i] = {
|
595
|
+
start: new Date(startMillis),
|
596
|
+
startFormatted: this.formatTime(new Date(startMillis), options.timeFormat),
|
597
|
+
end: new Date(endMillis),
|
598
|
+
endFormatted: this.formatTime(new Date(endMillis), options.timeFormat)
|
599
|
+
};
|
600
|
+
startMillis = endMillis;
|
601
|
+
}
|
602
|
+
return times;
|
603
|
+
},
|
604
|
+
|
605
|
+
formatDate: function(date, format) {
|
606
|
+
if (format) {
|
607
|
+
return this._formatDate(date, format);
|
608
|
+
} else {
|
609
|
+
return this._formatDate(date, this.options.dateFormat);
|
610
|
+
}
|
611
|
+
},
|
612
|
+
|
613
|
+
formatTime: function(date, format) {
|
614
|
+
if (format) {
|
615
|
+
return this._formatDate(date, format);
|
616
|
+
} else if (this.options.timeFormat) {
|
617
|
+
return this._formatDate(date, this.options.timeFormat);
|
618
|
+
} else if (this.options.use24Hour) {
|
619
|
+
return this._formatDate(date, 'H:i');
|
620
|
+
} else {
|
621
|
+
return this._formatDate(date, 'h:i a');
|
622
|
+
}
|
623
|
+
},
|
624
|
+
|
625
|
+
serializeEvents: function() {
|
626
|
+
var self = this;
|
627
|
+
var calEvents = [];
|
628
|
+
|
629
|
+
self.element.find('.wc-cal-event').each(function() {
|
630
|
+
calEvents.push($(this).data('calEvent'));
|
631
|
+
});
|
632
|
+
return calEvents;
|
633
|
+
},
|
634
|
+
|
635
|
+
next: function() {
|
636
|
+
if (this._startOnFirstDayOfWeek()) {
|
637
|
+
return this.nextWeek();
|
638
|
+
}
|
639
|
+
var newDate = new Date(this.element.data('startDate').getTime());
|
640
|
+
newDate.setDate(newDate.getDate() + this.options.daysToShow);
|
641
|
+
|
642
|
+
this._clearCalendar();
|
643
|
+
this._loadCalEvents(newDate);
|
644
|
+
},
|
645
|
+
|
646
|
+
prev: function() {
|
647
|
+
if (this._startOnFirstDayOfWeek()) {
|
648
|
+
return this.prevWeek();
|
649
|
+
}
|
650
|
+
var newDate = new Date(this.element.data('startDate').getTime());
|
651
|
+
newDate.setDate(newDate.getDate() - this.options.daysToShow);
|
652
|
+
|
653
|
+
this._clearCalendar();
|
654
|
+
this._loadCalEvents(newDate);
|
655
|
+
},
|
656
|
+
getCurrentFirstDay: function() {
|
657
|
+
return this._dateFirstDayOfWeek(this.options.date || new Date());
|
658
|
+
},
|
659
|
+
getCurrentLastDay: function() {
|
660
|
+
return this._addDays(this.getCurrentFirstDay(), this.options.daysToShow - 1);
|
661
|
+
},
|
662
|
+
|
663
|
+
/*********************
|
664
|
+
* private functions *
|
665
|
+
*********************/
|
666
|
+
_setOption: function(key, value) {
|
667
|
+
var self = this;
|
668
|
+
if (self.options[key] != value) {
|
669
|
+
// event callback change, no need to re-render the events
|
670
|
+
if (key == 'beforeEventNew') {
|
671
|
+
self.options[key] = value;
|
672
|
+
return;
|
673
|
+
}
|
674
|
+
|
675
|
+
// this could be made more efficient at some stage by caching the
|
676
|
+
// events array locally in a store but this should be done in conjunction
|
677
|
+
// with a proper binding model.
|
678
|
+
|
679
|
+
var currentEvents = $.map(self.element.find('.wc-cal-event'), function() {
|
680
|
+
return $(this).data('calEvent');
|
681
|
+
});
|
682
|
+
|
683
|
+
var newOptions = {};
|
684
|
+
newOptions[key] = value;
|
685
|
+
self._renderEvents({events: currentEvents, options: newOptions}, self.element.find('.wc-day-column-inner'));
|
686
|
+
}
|
687
|
+
},
|
688
|
+
|
689
|
+
// compute dynamic options based on other config values
|
690
|
+
_computeOptions: function() {
|
691
|
+
var options = this.options;
|
692
|
+
if (options.businessHours.limitDisplay) {
|
693
|
+
options.timeslotsPerDay = options.timeslotsPerHour * (options.businessHours.end - options.businessHours.start);
|
694
|
+
options.millisToDisplay = (options.businessHours.end - options.businessHours.start) * 3600000; // 60 * 60 * 1000
|
695
|
+
options.millisPerTimeslot = options.millisToDisplay / options.timeslotsPerDay;
|
696
|
+
} else {
|
697
|
+
options.timeslotsPerDay = options.timeslotsPerHour * 24;
|
698
|
+
options.millisToDisplay = MILLIS_IN_DAY;
|
699
|
+
options.millisPerTimeslot = MILLIS_IN_DAY / options.timeslotsPerDay;
|
700
|
+
}
|
701
|
+
},
|
702
|
+
|
703
|
+
/*
|
704
|
+
* Resize the calendar scrollable height based on the provided function in options.
|
705
|
+
*/
|
706
|
+
_resizeCalendar: function() {
|
707
|
+
var options = this.options;
|
708
|
+
if (options && $.isFunction(options.height)) {
|
709
|
+
var calendarHeight = options.height(this.element);
|
710
|
+
var headerHeight = this.element.find('.wc-header').outerHeight();
|
711
|
+
var navHeight = this.element.find('.wc-toolbar').outerHeight();
|
712
|
+
var scrollContainerHeight = Math.max(calendarHeight - navHeight - headerHeight, options.minBodyHeight);
|
713
|
+
var timeslotHeight = this.element.find('.wc-time-slots').outerHeight();
|
714
|
+
this.element.find('.wc-scrollable-grid').height(scrollContainerHeight);
|
715
|
+
if (timeslotHeight <= scrollContainerHeight) {
|
716
|
+
this.element.find('.wc-scrollbar-shim').width(0);
|
717
|
+
}
|
718
|
+
else {
|
719
|
+
this.element.find('.wc-scrollbar-shim').width(this._findScrollBarWidth());
|
720
|
+
}
|
721
|
+
this._trigger('resize', this.element);
|
722
|
+
}
|
723
|
+
},
|
724
|
+
|
725
|
+
_findScrollBarWidth: function() {
|
726
|
+
var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');
|
727
|
+
var child = parent.children();
|
728
|
+
var width = child.innerWidth() - child.height(99).innerWidth();
|
729
|
+
parent.remove();
|
730
|
+
return width || /* default to 16 that is the average */ 16;
|
731
|
+
},
|
732
|
+
|
733
|
+
/*
|
734
|
+
* configure calendar interaction events that are able to use event
|
735
|
+
* delegation for greater efficiency
|
736
|
+
*/
|
737
|
+
_setupEventDelegation: function() {
|
738
|
+
var self = this;
|
739
|
+
var options = this.options;
|
740
|
+
this.element.click(function(event) {
|
741
|
+
var $target = $(event.target),
|
742
|
+
freeBusyManager;
|
743
|
+
if ($target.data('preventClick')) {
|
744
|
+
return;
|
745
|
+
}
|
746
|
+
var $calEvent = $target.hasClass('wc-cal-event') ? $target : $target.parents('.wc-cal-event');
|
747
|
+
if ($calEvent.length) {
|
748
|
+
freeBusyManager = self.getFreeBusyManagerForEvent($calEvent.data('calEvent'));
|
749
|
+
if (options.allowEventDelete && $target.hasClass('wc-cal-event-delete')) {
|
750
|
+
options.eventDelete($calEvent.data('calEvent'), $calEvent, freeBusyManager, self.element, event);
|
751
|
+
}else{
|
752
|
+
options.eventClick($calEvent.data('calEvent'), $calEvent, freeBusyManager, self.element, event);
|
753
|
+
}
|
754
|
+
}
|
755
|
+
}).mouseover(function(event) {
|
756
|
+
var $target = $(event.target);
|
757
|
+
|
758
|
+
if (self._isDraggingOrResizing($target)) {
|
759
|
+
return;
|
760
|
+
}
|
761
|
+
|
762
|
+
if ($target.hasClass('wc-cal-event')) {
|
763
|
+
options.eventMouseover($target.data('calEvent'), $target, event);
|
764
|
+
}
|
765
|
+
}).mouseout(function(event) {
|
766
|
+
var $target = $(event.target);
|
767
|
+
if (self._isDraggingOrResizing($target)) {
|
768
|
+
return;
|
769
|
+
}
|
770
|
+
if ($target.hasClass('wc-cal-event')) {
|
771
|
+
if ($target.data('sizing')) { return;}
|
772
|
+
options.eventMouseout($target.data('calEvent'), $target, event);
|
773
|
+
}
|
774
|
+
});
|
775
|
+
},
|
776
|
+
|
777
|
+
/*
|
778
|
+
* check if a ui draggable or resizable is currently being dragged or resized
|
779
|
+
*/
|
780
|
+
_isDraggingOrResizing: function($target) {
|
781
|
+
return $target.hasClass('ui-draggable-dragging') || $target.hasClass('ui-resizable-resizing');
|
782
|
+
},
|
783
|
+
|
784
|
+
/*
|
785
|
+
* Render the main calendar layout
|
786
|
+
*/
|
787
|
+
_renderCalendar: function() {
|
788
|
+
var $calendarContainer, $weekDayColumns;
|
789
|
+
var self = this;
|
790
|
+
var options = this.options;
|
791
|
+
|
792
|
+
$calendarContainer = $('<div class=\"ui-widget wc-container\">').appendTo(self.element);
|
793
|
+
|
794
|
+
//render the different parts
|
795
|
+
// nav links
|
796
|
+
self._renderCalendarButtons($calendarContainer);
|
797
|
+
// header
|
798
|
+
self._renderCalendarHeader($calendarContainer);
|
799
|
+
// body
|
800
|
+
self._renderCalendarBody($calendarContainer);
|
801
|
+
|
802
|
+
$weekDayColumns = $calendarContainer.find('.wc-day-column-inner');
|
803
|
+
$weekDayColumns.each(function(i, val) {
|
804
|
+
if (!options.readonly) {
|
805
|
+
self._addDroppableToWeekDay($(this));
|
806
|
+
if (options.allowEventCreation) {
|
807
|
+
self._setupEventCreationForWeekDay($(this));
|
808
|
+
}
|
809
|
+
}
|
810
|
+
});
|
811
|
+
},
|
812
|
+
|
813
|
+
/**
|
814
|
+
* render the nav buttons on top of the calendar
|
815
|
+
*/
|
816
|
+
_renderCalendarButtons: function($calendarContainer) {
|
817
|
+
var self = this, options = this.options;
|
818
|
+
if (options.buttons) {
|
819
|
+
var calendarNavHtml = '';
|
820
|
+
|
821
|
+
calendarNavHtml += '<div class=\"ui-widget-header wc-toolbar\">';
|
822
|
+
calendarNavHtml += '<div class=\"wc-display\"></div>';
|
823
|
+
calendarNavHtml += '<div class=\"wc-nav\">';
|
824
|
+
calendarNavHtml += '<button class=\"wc-prev\">' + options.buttonText.lastWeek + '</button>';
|
825
|
+
calendarNavHtml += '<button class=\"wc-today\">' + options.buttonText.today + '</button>';
|
826
|
+
calendarNavHtml += '<button class=\"wc-next\">' + options.buttonText.nextWeek + '</button>';
|
827
|
+
calendarNavHtml += '</div>';
|
828
|
+
calendarNavHtml += '<h1 class=\"wc-title\"></h1>';
|
829
|
+
calendarNavHtml += '</div>';
|
830
|
+
|
831
|
+
$(calendarNavHtml).appendTo($calendarContainer);
|
832
|
+
|
833
|
+
$calendarContainer.find('.wc-nav .wc-today')
|
834
|
+
.button({
|
835
|
+
icons: {primary: 'ui-icon-home'}})
|
836
|
+
.click(function() {
|
837
|
+
self.today();
|
838
|
+
return false;
|
839
|
+
});
|
840
|
+
|
841
|
+
$calendarContainer.find('.wc-nav .wc-prev')
|
842
|
+
.button({
|
843
|
+
text: false,
|
844
|
+
icons: {primary: 'ui-icon-seek-prev'}})
|
845
|
+
.click(function() {
|
846
|
+
self.element.weekCalendar('prev');
|
847
|
+
return false;
|
848
|
+
});
|
849
|
+
|
850
|
+
$calendarContainer.find('.wc-nav .wc-next')
|
851
|
+
.button({
|
852
|
+
text: false,
|
853
|
+
icons: {primary: 'ui-icon-seek-next'}})
|
854
|
+
.click(function() {
|
855
|
+
self.element.weekCalendar('next');
|
856
|
+
return false;
|
857
|
+
});
|
858
|
+
|
859
|
+
// now add buttons to switch display
|
860
|
+
if (this.options.switchDisplay && $.isPlainObject(this.options.switchDisplay)) {
|
861
|
+
var $container = $calendarContainer.find('.wc-display');
|
862
|
+
$.each(this.options.switchDisplay, function(label, option) {
|
863
|
+
var _id = 'wc-switch-display-' + option;
|
864
|
+
var _input = $('<input type="radio" id="' + _id + '" name="wc-switch-display" class="wc-switch-display"/>');
|
865
|
+
var _label = $('<label for="' + _id + '"></label>');
|
866
|
+
_label.html(label);
|
867
|
+
_input.val(option);
|
868
|
+
if (parseInt(self.options.daysToShow, 10) === parseInt(option, 10)) {
|
869
|
+
_input.attr('checked', 'checked');
|
870
|
+
}
|
871
|
+
$container
|
872
|
+
.append(_input)
|
873
|
+
.append(_label);
|
874
|
+
});
|
875
|
+
$container.find('input').change(function() {
|
876
|
+
self.setDaysToShow(parseInt($(this).val(), 10));
|
877
|
+
});
|
878
|
+
}
|
879
|
+
$calendarContainer.find('.wc-nav, .wc-display').buttonset();
|
880
|
+
var _height = $calendarContainer.find('.wc-nav').outerHeight();
|
881
|
+
$calendarContainer.find('.wc-title')
|
882
|
+
.height(_height)
|
883
|
+
.css('line-height', _height + 'px');
|
884
|
+
}else{
|
885
|
+
var calendarNavHtml = '';
|
886
|
+
calendarNavHtml += '<div class=\"ui-widget-header wc-toolbar\">';
|
887
|
+
calendarNavHtml += '<h1 class=\"wc-title\"></h1>';
|
888
|
+
calendarNavHtml += '</div>';
|
889
|
+
$(calendarNavHtml).appendTo($calendarContainer);
|
890
|
+
|
891
|
+
}
|
892
|
+
},
|
893
|
+
|
894
|
+
/**
|
895
|
+
* render the calendar header, including date and user header
|
896
|
+
*/
|
897
|
+
_renderCalendarHeader: function($calendarContainer) {
|
898
|
+
var self = this, options = this.options,
|
899
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
900
|
+
rowspan = '', colspan = '', calendarHeaderHtml;
|
901
|
+
|
902
|
+
if (showAsSeparatedUser) {
|
903
|
+
rowspan = ' rowspan=\"2\"';
|
904
|
+
colspan = ' colspan=\"' + options.users.length + '\" ';
|
905
|
+
}
|
906
|
+
|
907
|
+
//first row
|
908
|
+
calendarHeaderHtml = '<div class=\"ui-widget-content wc-header\">';
|
909
|
+
calendarHeaderHtml += '<table><tbody><tr><td class=\"wc-time-column-header\"></td>';
|
910
|
+
for (var i = 1; i <= options.daysToShow; i++) {
|
911
|
+
calendarHeaderHtml += '<td class=\"wc-day-column-header wc-day-' + i + '\"' + colspan + '></td>';
|
912
|
+
}
|
913
|
+
calendarHeaderHtml += '<td class=\"wc-scrollbar-shim\"' + rowspan + '></td></tr>';
|
914
|
+
|
915
|
+
//users row
|
916
|
+
if (showAsSeparatedUser) {
|
917
|
+
calendarHeaderHtml += '<tr><td class=\"wc-time-column-header\"></td>';
|
918
|
+
var uLength = options.users.length,
|
919
|
+
_headerClass = '';
|
920
|
+
|
921
|
+
for (var i = 1; i <= options.daysToShow; i++) {
|
922
|
+
for (var j = 0; j < uLength; j++) {
|
923
|
+
_headerClass = [];
|
924
|
+
if (j == 0) {
|
925
|
+
_headerClass.push('wc-day-column-first');
|
926
|
+
}
|
927
|
+
if (j == uLength - 1) {
|
928
|
+
_headerClass.push('wc-day-column-last');
|
929
|
+
}
|
930
|
+
if (!_headerClass.length) {
|
931
|
+
_headerClass = 'wc-day-column-middle';
|
932
|
+
}
|
933
|
+
else {
|
934
|
+
_headerClass = _headerClass.join(' ');
|
935
|
+
}
|
936
|
+
calendarHeaderHtml += '<td class=\"' + _headerClass + ' wc-user-header wc-day-' + i + ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
|
937
|
+
// calendarHeaderHtml+= "<div class=\"wc-user-header wc-day-" + i + " wc-user-" + self._getUserIdFromIndex(j) +"\" >";
|
938
|
+
calendarHeaderHtml += self._getUserName(j);
|
939
|
+
// calendarHeaderHtml+= "</div>";
|
940
|
+
calendarHeaderHtml += '</td>';
|
941
|
+
}
|
942
|
+
}
|
943
|
+
calendarHeaderHtml += '</tr>';
|
944
|
+
}
|
945
|
+
//close the header
|
946
|
+
calendarHeaderHtml += '</tbody></table></div>';
|
947
|
+
|
948
|
+
$(calendarHeaderHtml).appendTo($calendarContainer);
|
949
|
+
},
|
950
|
+
|
951
|
+
/**
|
952
|
+
* render the calendar body.
|
953
|
+
* Calendar body is composed of several distinct parts.
|
954
|
+
* Each part is displayed in a separated row to ease rendering.
|
955
|
+
* for further explanations, see each part rendering function.
|
956
|
+
*/
|
957
|
+
_renderCalendarBody: function($calendarContainer) {
|
958
|
+
var self = this, options = this.options,
|
959
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
960
|
+
$calendarBody, $calendarTableTbody;
|
961
|
+
// create the structure
|
962
|
+
$calendarBody = '<div class=\"wc-scrollable-grid\">';
|
963
|
+
$calendarBody += '<table class=\"wc-time-slots\">';
|
964
|
+
$calendarBody += '<tbody>';
|
965
|
+
$calendarBody += '</tbody>';
|
966
|
+
$calendarBody += '</table>';
|
967
|
+
$calendarBody += '</div>';
|
968
|
+
$calendarBody = $($calendarBody);
|
969
|
+
$calendarTableTbody = $calendarBody.find('tbody');
|
970
|
+
|
971
|
+
self._renderCalendarBodyTimeSlots($calendarTableTbody);
|
972
|
+
self._renderCalendarBodyOddEven($calendarTableTbody);
|
973
|
+
self._renderCalendarBodyFreeBusy($calendarTableTbody);
|
974
|
+
self._renderCalendarBodyEvents($calendarTableTbody);
|
975
|
+
|
976
|
+
$calendarBody.appendTo($calendarContainer);
|
977
|
+
|
978
|
+
//set the column height
|
979
|
+
$calendarContainer.find('.wc-full-height-column').height(options.timeslotHeight * options.timeslotsPerDay);
|
980
|
+
//set the timeslot height
|
981
|
+
$calendarContainer.find('.wc-time-slot').height(options.timeslotHeight - 1); //account for border
|
982
|
+
//init the time row header height
|
983
|
+
/**
|
984
|
+
TODO if total height for an hour is less than 11px, there is a display problem.
|
985
|
+
Find a way to handle it
|
986
|
+
*/
|
987
|
+
$calendarContainer.find('.wc-time-header-cell').css({
|
988
|
+
height: (options.timeslotHeight * options.timeslotsPerHour) - 11,
|
989
|
+
padding: 5
|
990
|
+
});
|
991
|
+
//add the user data to every impacted column
|
992
|
+
if (showAsSeparatedUser) {
|
993
|
+
for (var i = 0, uLength = options.users.length; i < uLength; i++) {
|
994
|
+
$calendarContainer.find('.wc-user-' + self._getUserIdFromIndex(i))
|
995
|
+
.data('wcUser', options.users[i])
|
996
|
+
.data('wcUserIndex', i)
|
997
|
+
.data('wcUserId', self._getUserIdFromIndex(i));
|
998
|
+
}
|
999
|
+
}
|
1000
|
+
},
|
1001
|
+
|
1002
|
+
/**
|
1003
|
+
* render the timeslots separation
|
1004
|
+
*/
|
1005
|
+
_renderCalendarBodyTimeSlots: function($calendarTableTbody) {
|
1006
|
+
var options = this.options,
|
1007
|
+
renderRow, i, j,
|
1008
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
1009
|
+
start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
|
1010
|
+
end = (options.businessHours.limitDisplay ? options.businessHours.end : 24),
|
1011
|
+
rowspan = 1;
|
1012
|
+
|
1013
|
+
//calculate the rowspan
|
1014
|
+
if (options.displayOddEven) { rowspan += 1; }
|
1015
|
+
if (options.displayFreeBusys) { rowspan += 1; }
|
1016
|
+
if (rowspan > 1) {
|
1017
|
+
rowspan = ' rowspan=\"' + rowspan + '\"';
|
1018
|
+
}
|
1019
|
+
else {
|
1020
|
+
rowspan = '';
|
1021
|
+
}
|
1022
|
+
|
1023
|
+
renderRow = '<tr class=\"wc-grid-row-timeslot\">';
|
1024
|
+
renderRow += '<td class=\"wc-grid-timeslot-header\"' + rowspan + '></td>';
|
1025
|
+
renderRow += '<td colspan=\"' + options.daysToShow * (showAsSeparatedUser ? options.users.length : 1) + '\">';
|
1026
|
+
renderRow += '<div class=\"wc-no-height-wrapper wc-time-slot-wrapper\">';
|
1027
|
+
renderRow += '<div class=\"wc-time-slots\">';
|
1028
|
+
|
1029
|
+
for (i = start; i < end; i++) {
|
1030
|
+
for (j = 0; j < options.timeslotsPerHour - 1; j++) {
|
1031
|
+
renderRow += '<div class=\"wc-time-slot\"></div>';
|
1032
|
+
}
|
1033
|
+
renderRow += '<div class=\"wc-time-slot wc-hour-end\"></div>';
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
renderRow += '</div>';
|
1037
|
+
renderRow += '</div>';
|
1038
|
+
renderRow += '</td>';
|
1039
|
+
renderRow += '</tr>';
|
1040
|
+
|
1041
|
+
$(renderRow).appendTo($calendarTableTbody);
|
1042
|
+
},
|
1043
|
+
|
1044
|
+
/**
|
1045
|
+
* render the odd even columns
|
1046
|
+
*/
|
1047
|
+
_renderCalendarBodyOddEven: function($calendarTableTbody) {
|
1048
|
+
if (this.options.displayOddEven) {
|
1049
|
+
var options = this.options,
|
1050
|
+
renderRow = '<tr class=\"wc-grid-row-oddeven\">',
|
1051
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
1052
|
+
oddEven,
|
1053
|
+
// let's take advantage of the jquery ui framework
|
1054
|
+
oddEvenClasses = {'odd': 'wc-column-odd', 'even': 'ui-state-hover wc-column-even'};
|
1055
|
+
|
1056
|
+
//now let's display oddEven placeholders
|
1057
|
+
for (var i = 1; i <= options.daysToShow; i++) {
|
1058
|
+
if (!showAsSeparatedUser) {
|
1059
|
+
oddEven = (oddEven == 'odd' ? 'even' : 'odd');
|
1060
|
+
renderRow += '<td class=\"wc-day-column day-' + i + '\">';
|
1061
|
+
renderRow += '<div class=\"wc-no-height-wrapper wc-oddeven-wrapper\">';
|
1062
|
+
renderRow += '<div class=\"wc-full-height-column ' + oddEvenClasses[oddEven] + '\"></div>';
|
1063
|
+
renderRow += '</div>';
|
1064
|
+
renderRow += '</td>';
|
1065
|
+
}
|
1066
|
+
else {
|
1067
|
+
var uLength = options.users.length;
|
1068
|
+
for (var j = 0; j < uLength; j++) {
|
1069
|
+
oddEven = (oddEven == 'odd' ? 'even' : 'odd');
|
1070
|
+
renderRow += '<td class=\"wc-day-column day-' + i + '\">';
|
1071
|
+
renderRow += '<div class=\"wc-no-height-wrapper wc-oddeven-wrapper\">';
|
1072
|
+
renderRow += '<div class=\"wc-full-height-column ' + oddEvenClasses[oddEven] + '\" ></div>';
|
1073
|
+
renderRow += '</div>';
|
1074
|
+
renderRow += '</td>';
|
1075
|
+
}
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
renderRow += '</tr>';
|
1079
|
+
|
1080
|
+
$(renderRow).appendTo($calendarTableTbody);
|
1081
|
+
}
|
1082
|
+
},
|
1083
|
+
|
1084
|
+
/**
|
1085
|
+
* render the freebusy placeholders
|
1086
|
+
*/
|
1087
|
+
_renderCalendarBodyFreeBusy: function($calendarTableTbody) {
|
1088
|
+
if (this.options.displayFreeBusys) {
|
1089
|
+
var self = this, options = this.options,
|
1090
|
+
renderRow = '<tr class=\"wc-grid-row-freebusy\">',
|
1091
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
|
1092
|
+
renderRow += '</td>';
|
1093
|
+
|
1094
|
+
//now let's display freebusy placeholders
|
1095
|
+
for (var i = 1; i <= options.daysToShow; i++) {
|
1096
|
+
if (options.displayFreeBusys) {
|
1097
|
+
if (!showAsSeparatedUser) {
|
1098
|
+
renderRow += '<td class=\"wc-day-column day-' + i + '\">';
|
1099
|
+
renderRow += '<div class=\"wc-no-height-wrapper wc-freebusy-wrapper\">';
|
1100
|
+
renderRow += '<div class=\"wc-full-height-column wc-column-freebusy wc-day-' + i + '\"></div>';
|
1101
|
+
renderRow += '</div>';
|
1102
|
+
renderRow += '</td>';
|
1103
|
+
}
|
1104
|
+
else {
|
1105
|
+
var uLength = options.users.length;
|
1106
|
+
for (var j = 0; j < uLength; j++) {
|
1107
|
+
renderRow += '<td class=\"wc-day-column day-' + i + '\">';
|
1108
|
+
renderRow += '<div class=\"wc-no-height-wrapper wc-freebusy-wrapper\">';
|
1109
|
+
renderRow += '<div class=\"wc-full-height-column wc-column-freebusy wc-day-' + i;
|
1110
|
+
renderRow += ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
|
1111
|
+
renderRow += '</div>';
|
1112
|
+
renderRow += '</div>';
|
1113
|
+
renderRow += '</td>';
|
1114
|
+
}
|
1115
|
+
}
|
1116
|
+
}
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
renderRow += '</tr>';
|
1120
|
+
|
1121
|
+
$(renderRow).appendTo($calendarTableTbody);
|
1122
|
+
}
|
1123
|
+
},
|
1124
|
+
|
1125
|
+
/**
|
1126
|
+
* render the calendar body for event placeholders
|
1127
|
+
*/
|
1128
|
+
_renderCalendarBodyEvents: function($calendarTableTbody) {
|
1129
|
+
var self = this, options = this.options,
|
1130
|
+
renderRow,
|
1131
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
1132
|
+
start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
|
1133
|
+
end = (options.businessHours.limitDisplay ? options.businessHours.end : 24);
|
1134
|
+
renderRow = '<tr class=\"wc-grid-row-events\">';
|
1135
|
+
renderRow += '<td class=\"wc-grid-timeslot-header\">';
|
1136
|
+
for (var i = start; i < end; i++) {
|
1137
|
+
var bhClass = (options.businessHours.start <= i && options.businessHours.end > i) ? 'ui-state-active wc-business-hours' : 'ui-state-default';
|
1138
|
+
renderRow += '<div class=\"wc-hour-header ' + bhClass + '\">';
|
1139
|
+
if (options.use24Hour) {
|
1140
|
+
renderRow += '<div class=\"wc-time-header-cell\">' + self._24HourForIndex(i) + '</div>';
|
1141
|
+
}
|
1142
|
+
else {
|
1143
|
+
renderRow += '<div class=\"wc-time-header-cell\">' + self._hourForIndex(i) + '<span class=\"wc-am-pm\">' + self._amOrPm(i) + '</span></div>';
|
1144
|
+
}
|
1145
|
+
renderRow += '</div>';
|
1146
|
+
}
|
1147
|
+
renderRow += '</td>';
|
1148
|
+
|
1149
|
+
//now let's display events placeholders
|
1150
|
+
var _columnBaseClass = 'ui-state-default wc-day-column';
|
1151
|
+
for (var i = 1; i <= options.daysToShow; i++) {
|
1152
|
+
if (!showAsSeparatedUser) {
|
1153
|
+
renderRow += '<td class=\"' + _columnBaseClass + ' wc-day-column-first wc-day-column-last day-' + i + '\">';
|
1154
|
+
renderRow += '<div class=\"wc-full-height-column wc-day-column-inner day-' + i + '\"></div>';
|
1155
|
+
renderRow += '</td>';
|
1156
|
+
}
|
1157
|
+
else {
|
1158
|
+
var uLength = options.users.length;
|
1159
|
+
var columnclass;
|
1160
|
+
for (var j = 0; j < uLength; j++) {
|
1161
|
+
columnclass = [];
|
1162
|
+
if (j == 0) {
|
1163
|
+
columnclass.push('wc-day-column-first');
|
1164
|
+
}
|
1165
|
+
if (j == uLength - 1) {
|
1166
|
+
columnclass.push('wc-day-column-last');
|
1167
|
+
}
|
1168
|
+
if (!columnclass.length) {
|
1169
|
+
columnclass = 'wc-day-column-middle';
|
1170
|
+
}
|
1171
|
+
else {
|
1172
|
+
columnclass = columnclass.join(' ');
|
1173
|
+
}
|
1174
|
+
renderRow += '<td class=\"' + _columnBaseClass + ' ' + columnclass + ' day-' + i + '\">';
|
1175
|
+
renderRow += '<div class=\"wc-full-height-column wc-day-column-inner day-' + i;
|
1176
|
+
renderRow += ' wc-user-' + self._getUserIdFromIndex(j) + '\">';
|
1177
|
+
renderRow += '</div>';
|
1178
|
+
renderRow += '</td>';
|
1179
|
+
}
|
1180
|
+
}
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
renderRow += '</tr>';
|
1184
|
+
|
1185
|
+
$(renderRow).appendTo($calendarTableTbody);
|
1186
|
+
},
|
1187
|
+
|
1188
|
+
/*
|
1189
|
+
* setup mouse events for capturing new events
|
1190
|
+
*/
|
1191
|
+
_setupEventCreationForWeekDay: function($weekDay) {
|
1192
|
+
var self = this;
|
1193
|
+
var options = this.options;
|
1194
|
+
$weekDay.mousedown(function(event) {
|
1195
|
+
var $target = $(event.target);
|
1196
|
+
if ($target.hasClass('wc-day-column-inner')) {
|
1197
|
+
|
1198
|
+
var $newEvent = $('<div class=\"wc-cal-event wc-new-cal-event wc-new-cal-event-creating\"></div>');
|
1199
|
+
|
1200
|
+
$newEvent.css({lineHeight: (options.timeslotHeight - 2) + 'px', fontSize: (options.timeslotHeight / 2) + 'px'});
|
1201
|
+
$target.append($newEvent);
|
1202
|
+
|
1203
|
+
var columnOffset = $target.offset().top;
|
1204
|
+
var clickY = event.pageY - columnOffset;
|
1205
|
+
var clickYRounded = (clickY - (clickY % options.timeslotHeight)) / options.timeslotHeight;
|
1206
|
+
var topPosition = clickYRounded * options.timeslotHeight;
|
1207
|
+
$newEvent.css({top: topPosition});
|
1208
|
+
|
1209
|
+
if (!options.preventDragOnEventCreation) {
|
1210
|
+
$target.bind('mousemove.newevent', function(event) {
|
1211
|
+
$newEvent.show();
|
1212
|
+
$newEvent.addClass('ui-resizable-resizing');
|
1213
|
+
var height = Math.round(event.pageY - columnOffset - topPosition);
|
1214
|
+
var remainder = height % options.timeslotHeight;
|
1215
|
+
//snap to closest timeslot
|
1216
|
+
if (remainder < 0) {
|
1217
|
+
var useHeight = height - remainder;
|
1218
|
+
$newEvent.css('height', useHeight < options.timeslotHeight ? options.timeslotHeight : useHeight);
|
1219
|
+
} else {
|
1220
|
+
$newEvent.css('height', height + (options.timeslotHeight - remainder));
|
1221
|
+
}
|
1222
|
+
}).mouseup(function() {
|
1223
|
+
$target.unbind('mousemove.newevent');
|
1224
|
+
$newEvent.addClass('ui-corner-all');
|
1225
|
+
});
|
1226
|
+
}
|
1227
|
+
}
|
1228
|
+
|
1229
|
+
}).mouseup(function(event) {
|
1230
|
+
var $target = $(event.target);
|
1231
|
+
|
1232
|
+
var $weekDay = $target.closest('.wc-day-column-inner');
|
1233
|
+
var $newEvent = $weekDay.find('.wc-new-cal-event-creating');
|
1234
|
+
|
1235
|
+
if ($newEvent.length) {
|
1236
|
+
var createdFromSingleClick = !$newEvent.hasClass('ui-resizable-resizing');
|
1237
|
+
|
1238
|
+
//if even created from a single click only, default height
|
1239
|
+
if (createdFromSingleClick) {
|
1240
|
+
$newEvent.css({height: options.timeslotHeight * options.defaultEventLength}).show();
|
1241
|
+
}
|
1242
|
+
var top = parseInt($newEvent.css('top'));
|
1243
|
+
var eventDuration = self._getEventDurationFromPositionedEventElement($weekDay, $newEvent, top);
|
1244
|
+
|
1245
|
+
$newEvent.remove();
|
1246
|
+
var newCalEvent = {start: eventDuration.start, end: eventDuration.end, title: options.newEventText};
|
1247
|
+
var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
|
1248
|
+
|
1249
|
+
if (showAsSeparatedUser) {
|
1250
|
+
newCalEvent = self._setEventUserId(newCalEvent, $weekDay.data('wcUserId'));
|
1251
|
+
}
|
1252
|
+
else if (!options.showAsSeparateUsers && options.users && options.users.length == 1) {
|
1253
|
+
newCalEvent = self._setEventUserId(newCalEvent, self._getUserIdFromIndex(0));
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
var freeBusyManager = self.getFreeBusyManagerForEvent(newCalEvent);
|
1257
|
+
|
1258
|
+
var $renderedCalEvent = self._renderEvent(newCalEvent, $weekDay);
|
1259
|
+
|
1260
|
+
if (!options.allowCalEventOverlap) {
|
1261
|
+
self._adjustForEventCollisions($weekDay, $renderedCalEvent, newCalEvent, newCalEvent);
|
1262
|
+
self._positionEvent($weekDay, $renderedCalEvent);
|
1263
|
+
} else {
|
1264
|
+
self._adjustOverlappingEvents($weekDay);
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
var proceed = self._trigger('beforeEventNew', event, {
|
1268
|
+
'calEvent': newCalEvent,
|
1269
|
+
'createdFromSingleClick': createdFromSingleClick,
|
1270
|
+
'calendar': self.element
|
1271
|
+
});
|
1272
|
+
if (proceed) {
|
1273
|
+
options.eventNew(newCalEvent, $renderedCalEvent, freeBusyManager, self.element, event);
|
1274
|
+
}
|
1275
|
+
else {
|
1276
|
+
$($renderedCalEvent).remove();
|
1277
|
+
}
|
1278
|
+
}
|
1279
|
+
});
|
1280
|
+
},
|
1281
|
+
|
1282
|
+
/*
|
1283
|
+
* load calendar events for the week based on the date provided
|
1284
|
+
*/
|
1285
|
+
_loadCalEvents: function(dateWithinWeek) {
|
1286
|
+
|
1287
|
+
var date, weekStartDate, weekEndDate, $weekDayColumns;
|
1288
|
+
var self = this;
|
1289
|
+
var options = this.options;
|
1290
|
+
date = this._fixMinMaxDate(dateWithinWeek || options.date);
|
1291
|
+
// if date is not provided
|
1292
|
+
// or was not set
|
1293
|
+
// or is different than old one
|
1294
|
+
if ((!date || !date.getTime) ||
|
1295
|
+
(!options.date || !options.date.getTime) ||
|
1296
|
+
date.getTime() != options.date.getTime()
|
1297
|
+
) {
|
1298
|
+
// trigger the changedate event
|
1299
|
+
this._trigger('changedate', this.element, date);
|
1300
|
+
}
|
1301
|
+
this.options.date = date;
|
1302
|
+
weekStartDate = self._dateFirstDayOfWeek(date);
|
1303
|
+
weekEndDate = self._dateLastMilliOfWeek(date);
|
1304
|
+
|
1305
|
+
options.calendarBeforeLoad(self.element);
|
1306
|
+
|
1307
|
+
self.element.data('startDate', weekStartDate);
|
1308
|
+
self.element.data('endDate', weekEndDate);
|
1309
|
+
|
1310
|
+
$weekDayColumns = self.element.find('.wc-day-column-inner');
|
1311
|
+
|
1312
|
+
self._updateDayColumnHeader($weekDayColumns);
|
1313
|
+
|
1314
|
+
//load events by chosen means
|
1315
|
+
if (typeof options.data == 'string') {
|
1316
|
+
if (options.loading) {
|
1317
|
+
options.loading(true);
|
1318
|
+
}
|
1319
|
+
if (_currentAjaxCall) {
|
1320
|
+
// first abort current request.
|
1321
|
+
if (!_jQuery14OrLower) {
|
1322
|
+
_currentAjaxCall.abort();
|
1323
|
+
} else {
|
1324
|
+
// due to the fact that jquery 1.4 does not detect a request was
|
1325
|
+
// aborted, we need to replace the onreadystatechange and
|
1326
|
+
// execute the "complete" callback.
|
1327
|
+
_currentAjaxCall.onreadystatechange = null;
|
1328
|
+
_currentAjaxCall.abort();
|
1329
|
+
_currentAjaxCall = null;
|
1330
|
+
if (options.loading) {
|
1331
|
+
options.loading(false);
|
1332
|
+
}
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
var jsonOptions = self._getJsonOptions();
|
1336
|
+
jsonOptions[options.startParam || 'start'] = Math.round(weekStartDate.getTime() / 1000);
|
1337
|
+
jsonOptions[options.endParam || 'end'] = Math.round(weekEndDate.getTime() / 1000);
|
1338
|
+
_currentAjaxCall = $.ajax({
|
1339
|
+
url: options.data,
|
1340
|
+
data: jsonOptions,
|
1341
|
+
dataType: 'json',
|
1342
|
+
error: function(XMLHttpRequest, textStatus, errorThrown) {
|
1343
|
+
// only prevent error with jQuery 1.5
|
1344
|
+
// see issue #34. thanks to dapplebeforedawn
|
1345
|
+
// (https://github.com/themouette/jquery-week-calendar/issues#issue/34)
|
1346
|
+
// for 1.5+, aborted request mean errorThrown == 'abort'
|
1347
|
+
// for prior version it means !errorThrown && !XMLHttpRequest.status
|
1348
|
+
// fixes #55
|
1349
|
+
if (errorThrown != 'abort' && XMLHttpRequest.status != 0) {
|
1350
|
+
alert('unable to get data, error:' + textStatus);
|
1351
|
+
}
|
1352
|
+
},
|
1353
|
+
success: function(data) {
|
1354
|
+
self._renderEvents(data, $weekDayColumns);
|
1355
|
+
},
|
1356
|
+
complete: function() {
|
1357
|
+
_currentAjaxCall = null;
|
1358
|
+
if (options.loading) {
|
1359
|
+
options.loading(false);
|
1360
|
+
}
|
1361
|
+
}
|
1362
|
+
});
|
1363
|
+
}
|
1364
|
+
else if ($.isFunction(options.data)) {
|
1365
|
+
options.data(weekStartDate, weekEndDate,
|
1366
|
+
function(data) {
|
1367
|
+
self._renderEvents(data, $weekDayColumns);
|
1368
|
+
});
|
1369
|
+
}
|
1370
|
+
else if (options.data) {
|
1371
|
+
self._renderEvents(options.data, $weekDayColumns);
|
1372
|
+
}
|
1373
|
+
|
1374
|
+
self._disableTextSelect($weekDayColumns);
|
1375
|
+
|
1376
|
+
|
1377
|
+
},
|
1378
|
+
|
1379
|
+
/*
|
1380
|
+
* update the display of each day column header based on the calendar week
|
1381
|
+
*/
|
1382
|
+
_updateDayColumnHeader: function($weekDayColumns) {
|
1383
|
+
var self = this;
|
1384
|
+
var options = this.options;
|
1385
|
+
var currentDay = self._cloneDate(self.element.data('startDate'));
|
1386
|
+
var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
|
1387
|
+
var todayClass = 'ui-state-active wc-today';
|
1388
|
+
|
1389
|
+
self.element.find('.wc-header td.wc-day-column-header').each(function(i, val) {
|
1390
|
+
$(this).html(self._getHeaderDate(currentDay));
|
1391
|
+
if (self._isToday(currentDay)) {
|
1392
|
+
$(this).addClass(todayClass);
|
1393
|
+
} else {
|
1394
|
+
$(this).removeClass(todayClass);
|
1395
|
+
}
|
1396
|
+
currentDay = self._addDays(currentDay, 1);
|
1397
|
+
|
1398
|
+
});
|
1399
|
+
|
1400
|
+
currentDay = self._cloneDate(self.element.data('startDate'));
|
1401
|
+
if (showAsSeparatedUser)
|
1402
|
+
{
|
1403
|
+
self.element.find('.wc-header td.wc-user-header').each(function(i, val) {
|
1404
|
+
if (self._isToday(currentDay)) {
|
1405
|
+
$(this).addClass(todayClass);
|
1406
|
+
} else {
|
1407
|
+
$(this).removeClass(todayClass);
|
1408
|
+
}
|
1409
|
+
currentDay = ((i + 1) % options.users.length) ? currentDay : self._addDays(currentDay, 1);
|
1410
|
+
});
|
1411
|
+
}
|
1412
|
+
|
1413
|
+
currentDay = self._cloneDate(self.element.data('startDate'));
|
1414
|
+
|
1415
|
+
$weekDayColumns.each(function(i, val) {
|
1416
|
+
|
1417
|
+
$(this).data('startDate', self._cloneDate(currentDay));
|
1418
|
+
$(this).data('endDate', new Date(currentDay.getTime() + (MILLIS_IN_DAY)));
|
1419
|
+
if (self._isToday(currentDay)) {
|
1420
|
+
$(this).parent()
|
1421
|
+
.addClass(todayClass)
|
1422
|
+
.removeClass('ui-state-default');
|
1423
|
+
} else {
|
1424
|
+
$(this).parent()
|
1425
|
+
.removeClass(todayClass)
|
1426
|
+
.addClass('ui-state-default');
|
1427
|
+
}
|
1428
|
+
|
1429
|
+
if (!showAsSeparatedUser || !((i + 1) % options.users.length)) {
|
1430
|
+
currentDay = self._addDays(currentDay, 1);
|
1431
|
+
}
|
1432
|
+
});
|
1433
|
+
|
1434
|
+
//now update the freeBusy placeholders
|
1435
|
+
if (options.displayFreeBusys) {
|
1436
|
+
currentDay = self._cloneDate(self.element.data('startDate'));
|
1437
|
+
self.element.find('.wc-grid-row-freebusy .wc-column-freebusy').each(function(i, val) {
|
1438
|
+
$(this).data('startDate', self._cloneDate(currentDay));
|
1439
|
+
$(this).data('endDate', new Date(currentDay.getTime() + (MILLIS_IN_DAY)));
|
1440
|
+
if (!showAsSeparatedUser || !((i + 1) % options.users.length)) {
|
1441
|
+
currentDay = self._addDays(currentDay, 1);
|
1442
|
+
}
|
1443
|
+
});
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
//now update the calendar title
|
1447
|
+
if (this.options.title && this.options.title.length) {
|
1448
|
+
var _date = this.options.date,
|
1449
|
+
_start = self._cloneDate(self.element.data('startDate')),
|
1450
|
+
_end = self._dateLastDayOfWeek(new Date(this._cloneDate(self.element.data('endDate')).getTime() - (MILLIS_IN_DAY))),
|
1451
|
+
_title = this._getCalendarTitle();
|
1452
|
+
_title = _title.split('%start%').join(self._formatDate(_start, options.dateFormat));
|
1453
|
+
_title = _title.split('%end%').join(self._formatDate(_end, options.dateFormat));
|
1454
|
+
_title = _title.split('%date%').join(self._formatDate(_date, options.dateFormat));
|
1455
|
+
$('.wc-toolbar .wc-title', self.element).html(_title);
|
1456
|
+
}
|
1457
|
+
//self._clearFreeBusys();
|
1458
|
+
},
|
1459
|
+
|
1460
|
+
/*
|
1461
|
+
* gets the calendar title options
|
1462
|
+
*/
|
1463
|
+
_getCalendarTitle: function() {
|
1464
|
+
if ($.isFunction(this.options.title)) {
|
1465
|
+
return this.options.title(this.options.daysToShow);
|
1466
|
+
}
|
1467
|
+
return this.options.title;
|
1468
|
+
},
|
1469
|
+
|
1470
|
+
/*
|
1471
|
+
* Render the events into the calendar
|
1472
|
+
*/
|
1473
|
+
_renderEvents: function(data, $weekDayColumns) {
|
1474
|
+
var self = this;
|
1475
|
+
var options = this.options;
|
1476
|
+
var eventsToRender;
|
1477
|
+
|
1478
|
+
if (data.options) {
|
1479
|
+
var updateLayout = false;
|
1480
|
+
//update options
|
1481
|
+
$.each(data.options, function(key, value) {
|
1482
|
+
if (value !== options[key]) {
|
1483
|
+
options[key] = value;
|
1484
|
+
updateLayout = updateLayout || $.ui.weekCalendar.updateLayoutOptions[key];
|
1485
|
+
}
|
1486
|
+
});
|
1487
|
+
|
1488
|
+
self._computeOptions();
|
1489
|
+
|
1490
|
+
if (updateLayout) {
|
1491
|
+
var hour = self._getCurrentScrollHour();
|
1492
|
+
self.element.empty();
|
1493
|
+
self._renderCalendar();
|
1494
|
+
$weekDayColumns = self.element.find('.wc-time-slots .wc-day-column-inner');
|
1495
|
+
self._updateDayColumnHeader($weekDayColumns);
|
1496
|
+
self._resizeCalendar();
|
1497
|
+
self._scrollToHour(hour, false);
|
1498
|
+
}
|
1499
|
+
}
|
1500
|
+
this._clearCalendar();
|
1501
|
+
|
1502
|
+
if ($.isArray(data)) {
|
1503
|
+
eventsToRender = self._cleanEvents(data);
|
1504
|
+
} else if (data.events) {
|
1505
|
+
eventsToRender = self._cleanEvents(data.events);
|
1506
|
+
//render the freebusys
|
1507
|
+
self._renderFreeBusys(data);
|
1508
|
+
}
|
1509
|
+
$.each(eventsToRender, function(i, calEvent) {
|
1510
|
+
//render a multi day event as various event :
|
1511
|
+
//thanks to http://github.com/fbeauchamp/jquery-week-calendar
|
1512
|
+
var initialStart = new Date(calEvent.start);
|
1513
|
+
var initialEnd = new Date(calEvent.end);
|
1514
|
+
var maxHour = self.options.businessHours.limitDisplay ? self.options.businessHours.end : 24;
|
1515
|
+
var minHour = self.options.businessHours.limitDisplay ? self.options.businessHours.start : 0;
|
1516
|
+
var start = new Date(initialStart);
|
1517
|
+
var startDate = self._formatDate(start, 'Ymd');
|
1518
|
+
var endDate = self._formatDate(initialEnd, 'Ymd');
|
1519
|
+
var $weekDay;
|
1520
|
+
var isMultiday = false;
|
1521
|
+
|
1522
|
+
while (startDate < endDate) {
|
1523
|
+
calEvent.start = start;
|
1524
|
+
//end of this virual calEvent is set to the end of the day
|
1525
|
+
calEvent.end.setFullYear(start.getFullYear());
|
1526
|
+
calEvent.end.setDate(start.getDate());
|
1527
|
+
calEvent.end.setMonth(start.getMonth());
|
1528
|
+
calEvent.end.setHours(maxHour);
|
1529
|
+
calEvent.end.setMinutes(0);
|
1530
|
+
calEvent.end.setSeconds(0);
|
1531
|
+
if (($weekDay = self._findWeekDayForEvent(calEvent, $weekDayColumns))) {
|
1532
|
+
self._renderEvent(calEvent, $weekDay);
|
1533
|
+
}
|
1534
|
+
//start is set to the begin of the new day
|
1535
|
+
start.setDate(start.getDate() + 1);
|
1536
|
+
start.setHours(minHour);
|
1537
|
+
start.setMinutes(0);
|
1538
|
+
start.setSeconds(0);
|
1539
|
+
startDate = self._formatDate(start, 'Ymd');
|
1540
|
+
isMultiday = true;
|
1541
|
+
}
|
1542
|
+
if (start <= initialEnd) {
|
1543
|
+
calEvent.start = start;
|
1544
|
+
calEvent.end = initialEnd;
|
1545
|
+
if (((isMultiday && calEvent.start.getTime() != calEvent.end.getTime()) || !isMultiday) && ($weekDay = self._findWeekDayForEvent(calEvent, $weekDayColumns))) {
|
1546
|
+
self._renderEvent(calEvent, $weekDay);
|
1547
|
+
}
|
1548
|
+
}
|
1549
|
+
|
1550
|
+
//put back the initial start date
|
1551
|
+
calEvent.start = initialStart;
|
1552
|
+
});
|
1553
|
+
|
1554
|
+
$weekDayColumns.each(function() {
|
1555
|
+
self._adjustOverlappingEvents($(this));
|
1556
|
+
});
|
1557
|
+
|
1558
|
+
options.calendarAfterLoad(self.element);
|
1559
|
+
|
1560
|
+
if (!eventsToRender.length) {
|
1561
|
+
options.noEvents();
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
},
|
1565
|
+
|
1566
|
+
/*
|
1567
|
+
* Render a specific event into the day provided. Assumes correct
|
1568
|
+
* day for calEvent date
|
1569
|
+
*/
|
1570
|
+
_renderEvent: function(calEvent, $weekDay) {
|
1571
|
+
var self = this;
|
1572
|
+
var options = this.options;
|
1573
|
+
if (calEvent.start.getTime() > calEvent.end.getTime()) {
|
1574
|
+
return; // can't render a negative height
|
1575
|
+
}
|
1576
|
+
|
1577
|
+
var eventClass, eventHtml, $calEventList, $modifiedEvent;
|
1578
|
+
|
1579
|
+
eventClass = calEvent.id ? 'wc-cal-event' : 'wc-cal-event wc-new-cal-event';
|
1580
|
+
eventHtml = '<div class=\"' + eventClass + ' ui-corner-all\">';
|
1581
|
+
eventHtml += '<div class=\"wc-time ui-corner-top\"></div>';
|
1582
|
+
eventHtml += '<div class=\"wc-title\"></div></div>';
|
1583
|
+
|
1584
|
+
$weekDay.each(function() {
|
1585
|
+
var $calEvent = $(eventHtml);
|
1586
|
+
$modifiedEvent = options.eventRender(calEvent, $calEvent);
|
1587
|
+
$calEvent = $modifiedEvent ? $modifiedEvent.appendTo($(this)) : $calEvent.appendTo($(this));
|
1588
|
+
$calEvent.css({lineHeight: (options.textSize + 2) + 'px', fontSize: options.textSize + 'px'});
|
1589
|
+
|
1590
|
+
self._refreshEventDetails(calEvent, $calEvent);
|
1591
|
+
self._positionEvent($(this), $calEvent);
|
1592
|
+
|
1593
|
+
//add to event list
|
1594
|
+
if ($calEventList) {
|
1595
|
+
$calEventList = $calEventList.add($calEvent);
|
1596
|
+
}
|
1597
|
+
else {
|
1598
|
+
$calEventList = $calEvent;
|
1599
|
+
}
|
1600
|
+
});
|
1601
|
+
$calEventList.show();
|
1602
|
+
|
1603
|
+
if (!options.readonly && options.resizable(calEvent, $calEventList)) {
|
1604
|
+
self._addResizableToCalEvent(calEvent, $calEventList, $weekDay);
|
1605
|
+
}
|
1606
|
+
if (!options.readonly && options.draggable(calEvent, $calEventList)) {
|
1607
|
+
self._addDraggableToCalEvent(calEvent, $calEventList);
|
1608
|
+
}
|
1609
|
+
options.eventAfterRender(calEvent, $calEventList);
|
1610
|
+
|
1611
|
+
return $calEventList;
|
1612
|
+
|
1613
|
+
},
|
1614
|
+
addEvent: function() {
|
1615
|
+
return this._renderEvent.apply(this, arguments);
|
1616
|
+
},
|
1617
|
+
|
1618
|
+
_adjustOverlappingEvents: function($weekDay) {
|
1619
|
+
var self = this;
|
1620
|
+
if (self.options.allowCalEventOverlap) {
|
1621
|
+
var groupsList = self._groupOverlappingEventElements($weekDay);
|
1622
|
+
$.each(groupsList, function() {
|
1623
|
+
var curGroups = this;
|
1624
|
+
$.each(curGroups, function(groupIndex) {
|
1625
|
+
var curGroup = this;
|
1626
|
+
|
1627
|
+
// do we want events to be displayed as overlapping
|
1628
|
+
if (self.options.overlapEventsSeparate) {
|
1629
|
+
var newWidth = self.options.totalEventsWidthPercentInOneColumn / curGroups.length;
|
1630
|
+
var newLeft = groupIndex * newWidth;
|
1631
|
+
} else {
|
1632
|
+
// TODO what happens when the group has more than 10 elements
|
1633
|
+
var newWidth = self.options.totalEventsWidthPercentInOneColumn - ((curGroups.length - 1) * 10);
|
1634
|
+
var newLeft = groupIndex * 10;
|
1635
|
+
}
|
1636
|
+
$.each(curGroup, function() {
|
1637
|
+
// bring mouseovered event to the front
|
1638
|
+
if (!self.options.overlapEventsSeparate) {
|
1639
|
+
$(this).bind('mouseover.z-index', function() {
|
1640
|
+
var $elem = $(this);
|
1641
|
+
$.each(curGroup, function() {
|
1642
|
+
$(this).css({'z-index': '1'});
|
1643
|
+
});
|
1644
|
+
$elem.css({'z-index': '3'});
|
1645
|
+
});
|
1646
|
+
}
|
1647
|
+
$(this).css({width: newWidth + '%', left: newLeft + '%', right: 0});
|
1648
|
+
});
|
1649
|
+
});
|
1650
|
+
});
|
1651
|
+
}
|
1652
|
+
},
|
1653
|
+
|
1654
|
+
|
1655
|
+
/*
|
1656
|
+
* Find groups of overlapping events
|
1657
|
+
*/
|
1658
|
+
_groupOverlappingEventElements: function($weekDay) {
|
1659
|
+
var $events = $weekDay.find('.wc-cal-event:visible');
|
1660
|
+
var sortedEvents = $events.sort(function(a, b) {
|
1661
|
+
return $(a).data('calEvent').start.getTime() - $(b).data('calEvent').start.getTime();
|
1662
|
+
});
|
1663
|
+
|
1664
|
+
var lastEndTime = new Date(0, 0, 0);
|
1665
|
+
var groups = [];
|
1666
|
+
var curGroups = [];
|
1667
|
+
var $curEvent;
|
1668
|
+
$.each(sortedEvents, function() {
|
1669
|
+
$curEvent = $(this);
|
1670
|
+
//checks, if the current group list is not empty, if the overlapping is finished
|
1671
|
+
if (curGroups.length > 0) {
|
1672
|
+
if (lastEndTime.getTime() <= $curEvent.data('calEvent').start.getTime()) {
|
1673
|
+
//finishes the current group list by adding it to the resulting list of groups and cleans it
|
1674
|
+
|
1675
|
+
groups.push(curGroups);
|
1676
|
+
curGroups = [];
|
1677
|
+
}
|
1678
|
+
}
|
1679
|
+
|
1680
|
+
//finds the first group to fill with the event
|
1681
|
+
for (var groupIndex = 0; groupIndex < curGroups.length; groupIndex++) {
|
1682
|
+
if (curGroups[groupIndex].length > 0) {
|
1683
|
+
//checks if the event starts after the end of the last event of the group
|
1684
|
+
if (curGroups[groupIndex][curGroups[groupIndex].length - 1].data('calEvent').end.getTime() <= $curEvent.data('calEvent').start.getTime()) {
|
1685
|
+
curGroups[groupIndex].push($curEvent);
|
1686
|
+
if (lastEndTime.getTime() < $curEvent.data('calEvent').end.getTime()) {
|
1687
|
+
lastEndTime = $curEvent.data('calEvent').end;
|
1688
|
+
}
|
1689
|
+
return;
|
1690
|
+
}
|
1691
|
+
}
|
1692
|
+
}
|
1693
|
+
//if not found, creates a new group
|
1694
|
+
curGroups.push([$curEvent]);
|
1695
|
+
if (lastEndTime.getTime() < $curEvent.data('calEvent').end.getTime()) {
|
1696
|
+
lastEndTime = $curEvent.data('calEvent').end;
|
1697
|
+
}
|
1698
|
+
});
|
1699
|
+
//adds the last groups in result
|
1700
|
+
if (curGroups.length > 0) {
|
1701
|
+
groups.push(curGroups);
|
1702
|
+
}
|
1703
|
+
return groups;
|
1704
|
+
},
|
1705
|
+
|
1706
|
+
|
1707
|
+
/*
|
1708
|
+
* find the weekday in the current calendar that the calEvent falls within
|
1709
|
+
*/
|
1710
|
+
_findWeekDayForEvent: function(calEvent, $weekDayColumns) {
|
1711
|
+
|
1712
|
+
var $weekDay,
|
1713
|
+
options = this.options,
|
1714
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
1715
|
+
user_ids = this._getEventUserId(calEvent);
|
1716
|
+
|
1717
|
+
if (!$.isArray(user_ids)) {
|
1718
|
+
user_ids = [user_ids];
|
1719
|
+
}
|
1720
|
+
|
1721
|
+
$weekDayColumns.each(function(index, curDay) {
|
1722
|
+
if ($(this).data('startDate').getTime() <= calEvent.start.getTime() &&
|
1723
|
+
$(this).data('endDate').getTime() >= calEvent.end.getTime() &&
|
1724
|
+
(!showAsSeparatedUser || $.inArray($(this).data('wcUserId'), user_ids) !== -1)
|
1725
|
+
) {
|
1726
|
+
if ($weekDay) {
|
1727
|
+
$weekDay = $weekDay.add($(curDay));
|
1728
|
+
}
|
1729
|
+
else {
|
1730
|
+
$weekDay = $(curDay);
|
1731
|
+
}
|
1732
|
+
}
|
1733
|
+
});
|
1734
|
+
|
1735
|
+
return $weekDay;
|
1736
|
+
},
|
1737
|
+
|
1738
|
+
/*
|
1739
|
+
* update the events rendering in the calendar. Add if does not yet exist.
|
1740
|
+
*/
|
1741
|
+
_updateEventInCalendar: function(calEvent) {
|
1742
|
+
var self = this;
|
1743
|
+
self._cleanEvent(calEvent);
|
1744
|
+
|
1745
|
+
if (calEvent.id) {
|
1746
|
+
self.element.find('.wc-cal-event').each(function() {
|
1747
|
+
if ($(this).data('calEvent').id === calEvent.id || $(this).hasClass('wc-new-cal-event')) {
|
1748
|
+
$(this).remove();
|
1749
|
+
// return false;
|
1750
|
+
}
|
1751
|
+
});
|
1752
|
+
}
|
1753
|
+
|
1754
|
+
var $weekDays = self._findWeekDayForEvent(calEvent, self.element.find('.wc-grid-row-events .wc-day-column-inner'));
|
1755
|
+
if ($weekDays) {
|
1756
|
+
$weekDays.each(function(index, weekDay) {
|
1757
|
+
var $weekDay = $(weekDay);
|
1758
|
+
var $calEvent = self._renderEvent(calEvent, $weekDay);
|
1759
|
+
self._adjustForEventCollisions($weekDay, $calEvent, calEvent, calEvent);
|
1760
|
+
self._refreshEventDetails(calEvent, $calEvent);
|
1761
|
+
self._positionEvent($weekDay, $calEvent);
|
1762
|
+
self._adjustOverlappingEvents($weekDay);
|
1763
|
+
});
|
1764
|
+
}
|
1765
|
+
},
|
1766
|
+
|
1767
|
+
/*
|
1768
|
+
* Position the event element within the weekday based on it's start / end dates.
|
1769
|
+
*/
|
1770
|
+
_positionEvent: function($weekDay, $calEvent) {
|
1771
|
+
var options = this.options;
|
1772
|
+
var calEvent = $calEvent.data('calEvent');
|
1773
|
+
var pxPerMillis = $weekDay.height() / options.millisToDisplay;
|
1774
|
+
var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
|
1775
|
+
var startMillis = this._getDSTdayShift(calEvent.start).getTime() - this._getDSTdayShift(new Date(calEvent.start.getFullYear(), calEvent.start.getMonth(), calEvent.start.getDate(), firstHourDisplayed)).getTime();
|
1776
|
+
var eventMillis = this._getDSTdayShift(calEvent.end).getTime() - this._getDSTdayShift(calEvent.start).getTime();
|
1777
|
+
var pxTop = pxPerMillis * startMillis;
|
1778
|
+
var pxHeight = pxPerMillis * eventMillis;
|
1779
|
+
//var pxHeightFallback = pxPerMillis * (60 / options.timeslotsPerHour) * 60 * 1000;
|
1780
|
+
$calEvent.css({top: pxTop, height: pxHeight || (pxPerMillis * 3600000 / options.timeslotsPerHour)});
|
1781
|
+
},
|
1782
|
+
|
1783
|
+
/*
|
1784
|
+
* Determine the actual start and end times of a calevent based on it's
|
1785
|
+
* relative position within the weekday column and the starting hour of the
|
1786
|
+
* displayed calendar.
|
1787
|
+
*/
|
1788
|
+
_getEventDurationFromPositionedEventElement: function($weekDay, $calEvent, top) {
|
1789
|
+
var options = this.options;
|
1790
|
+
var startOffsetMillis = options.businessHours.limitDisplay ? options.businessHours.start * 3600000 : 0;
|
1791
|
+
var start = new Date($weekDay.data('startDate').getTime() + startOffsetMillis + Math.round(top / options.timeslotHeight) * options.millisPerTimeslot);
|
1792
|
+
var end = new Date(start.getTime() + ($calEvent.height() / options.timeslotHeight) * options.millisPerTimeslot);
|
1793
|
+
return {start: this._getDSTdayShift(start, -1), end: this._getDSTdayShift(end, -1)};
|
1794
|
+
},
|
1795
|
+
|
1796
|
+
/*
|
1797
|
+
* If the calendar does not allow event overlap, adjust the start or end date if necessary to
|
1798
|
+
* avoid overlapping of events. Typically, shortens the resized / dropped event to it's max possible
|
1799
|
+
* duration based on the overlap. If no satisfactory adjustment can be made, the event is reverted to
|
1800
|
+
* it's original location.
|
1801
|
+
*/
|
1802
|
+
_adjustForEventCollisions: function($weekDay, $calEvent, newCalEvent, oldCalEvent, maintainEventDuration) {
|
1803
|
+
var options = this.options;
|
1804
|
+
|
1805
|
+
if (options.allowCalEventOverlap) {
|
1806
|
+
return;
|
1807
|
+
}
|
1808
|
+
var adjustedStart, adjustedEnd;
|
1809
|
+
var self = this;
|
1810
|
+
|
1811
|
+
$weekDay.find('.wc-cal-event').not($calEvent).each(function() {
|
1812
|
+
var currentCalEvent = $(this).data('calEvent');
|
1813
|
+
|
1814
|
+
//has been dropped onto existing event overlapping the end time
|
1815
|
+
if (newCalEvent.start.getTime() < currentCalEvent.end.getTime() &&
|
1816
|
+
newCalEvent.end.getTime() >= currentCalEvent.end.getTime()) {
|
1817
|
+
|
1818
|
+
adjustedStart = currentCalEvent.end;
|
1819
|
+
}
|
1820
|
+
|
1821
|
+
|
1822
|
+
//has been dropped onto existing event overlapping the start time
|
1823
|
+
if (newCalEvent.end.getTime() > currentCalEvent.start.getTime() &&
|
1824
|
+
newCalEvent.start.getTime() <= currentCalEvent.start.getTime()) {
|
1825
|
+
|
1826
|
+
adjustedEnd = currentCalEvent.start;
|
1827
|
+
}
|
1828
|
+
//has been dropped inside existing event with same or larger duration
|
1829
|
+
if (oldCalEvent.resizable == false ||
|
1830
|
+
(newCalEvent.end.getTime() <= currentCalEvent.end.getTime() &&
|
1831
|
+
newCalEvent.start.getTime() >= currentCalEvent.start.getTime())) {
|
1832
|
+
|
1833
|
+
adjustedStart = oldCalEvent.start;
|
1834
|
+
adjustedEnd = oldCalEvent.end;
|
1835
|
+
return false;
|
1836
|
+
}
|
1837
|
+
|
1838
|
+
});
|
1839
|
+
|
1840
|
+
|
1841
|
+
newCalEvent.start = adjustedStart || newCalEvent.start;
|
1842
|
+
|
1843
|
+
if (adjustedStart && maintainEventDuration) {
|
1844
|
+
newCalEvent.end = new Date(adjustedStart.getTime() + (oldCalEvent.end.getTime() - oldCalEvent.start.getTime()));
|
1845
|
+
self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, oldCalEvent);
|
1846
|
+
} else {
|
1847
|
+
newCalEvent.end = adjustedEnd || newCalEvent.end;
|
1848
|
+
}
|
1849
|
+
|
1850
|
+
|
1851
|
+
//reset if new cal event has been forced to zero size
|
1852
|
+
if (newCalEvent.start.getTime() >= newCalEvent.end.getTime()) {
|
1853
|
+
newCalEvent.start = oldCalEvent.start;
|
1854
|
+
newCalEvent.end = oldCalEvent.end;
|
1855
|
+
}
|
1856
|
+
|
1857
|
+
$calEvent.data('calEvent', newCalEvent);
|
1858
|
+
},
|
1859
|
+
|
1860
|
+
/*
|
1861
|
+
* Add draggable capabilities to an event
|
1862
|
+
*/
|
1863
|
+
_addDraggableToCalEvent: function(calEvent, $calEvent) {
|
1864
|
+
var options = this.options;
|
1865
|
+
$calEvent.draggable({
|
1866
|
+
handle: '.wc-time',
|
1867
|
+
containment: 'div.wc-time-slots',
|
1868
|
+
snap: '.wc-day-column-inner',
|
1869
|
+
snapMode: 'inner',
|
1870
|
+
snapTolerance: options.timeslotHeight - 1,
|
1871
|
+
revert: 'invalid',
|
1872
|
+
opacity: 0.5,
|
1873
|
+
grid: [$calEvent.outerWidth() + 1, options.timeslotHeight],
|
1874
|
+
start: function(event, ui) {
|
1875
|
+
var $calEvent = ui.draggable;
|
1876
|
+
options.eventDrag(calEvent, $calEvent);
|
1877
|
+
}
|
1878
|
+
});
|
1879
|
+
},
|
1880
|
+
|
1881
|
+
/*
|
1882
|
+
* Add droppable capabilites to weekdays to allow dropping of calEvents only
|
1883
|
+
*/
|
1884
|
+
_addDroppableToWeekDay: function($weekDay) {
|
1885
|
+
var self = this;
|
1886
|
+
var options = this.options;
|
1887
|
+
$weekDay.droppable({
|
1888
|
+
accept: '.wc-cal-event',
|
1889
|
+
drop: function(event, ui) {
|
1890
|
+
var $calEvent = ui.draggable;
|
1891
|
+
var top = Math.round(parseInt(ui.position.top));
|
1892
|
+
var eventDuration = self._getEventDurationFromPositionedEventElement($weekDay, $calEvent, top);
|
1893
|
+
var calEvent = $calEvent.data('calEvent');
|
1894
|
+
var newCalEvent = $.extend(true, {}, calEvent, {start: eventDuration.start, end: eventDuration.end});
|
1895
|
+
var showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length;
|
1896
|
+
if (showAsSeparatedUser) {
|
1897
|
+
// we may have dragged the event on column with a new user.
|
1898
|
+
// nice way to handle that is:
|
1899
|
+
// - get the newly dragged on user
|
1900
|
+
// - check if user is part of the event
|
1901
|
+
// - if yes, nothing changes, if not, find the old owner to remove it and add new one
|
1902
|
+
var newUserId = $weekDay.data('wcUserId');
|
1903
|
+
var userIdList = self._getEventUserId(calEvent);
|
1904
|
+
var oldUserId = $(ui.draggable.parents('.wc-day-column-inner').get(0)).data('wcUserId');
|
1905
|
+
if (!$.isArray(userIdList)) {
|
1906
|
+
userIdList = [userIdList];
|
1907
|
+
}
|
1908
|
+
if ($.inArray(newUserId, userIdList) == -1) {
|
1909
|
+
// remove old user
|
1910
|
+
var _index = $.inArray(oldUserId, userIdList);
|
1911
|
+
userIdList.splice(_index, 1);
|
1912
|
+
// add new user ?
|
1913
|
+
if ($.inArray(newUserId, userIdList) == -1) {
|
1914
|
+
userIdList.push(newUserId);
|
1915
|
+
}
|
1916
|
+
}
|
1917
|
+
newCalEvent = self._setEventUserId(newCalEvent, ((userIdList.length == 1) ? userIdList[0] : userIdList));
|
1918
|
+
}
|
1919
|
+
self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, calEvent, true);
|
1920
|
+
var $weekDayColumns = self.element.find('.wc-day-column-inner');
|
1921
|
+
|
1922
|
+
//trigger drop callback
|
1923
|
+
options.eventDrop(newCalEvent, calEvent, $calEvent);
|
1924
|
+
|
1925
|
+
var $newEvent = self._renderEvent(newCalEvent, self._findWeekDayForEvent(newCalEvent, $weekDayColumns));
|
1926
|
+
$calEvent.hide();
|
1927
|
+
|
1928
|
+
$calEvent.data('preventClick', true);
|
1929
|
+
|
1930
|
+
var $weekDayOld = self._findWeekDayForEvent($calEvent.data('calEvent'), self.element.find('.wc-time-slots .wc-day-column-inner'));
|
1931
|
+
|
1932
|
+
if ($weekDayOld.data('startDate') != $weekDay.data('startDate')) {
|
1933
|
+
self._adjustOverlappingEvents($weekDayOld);
|
1934
|
+
}
|
1935
|
+
self._adjustOverlappingEvents($weekDay);
|
1936
|
+
|
1937
|
+
setTimeout(function() {
|
1938
|
+
$calEvent.remove();
|
1939
|
+
}, 1000);
|
1940
|
+
|
1941
|
+
}
|
1942
|
+
});
|
1943
|
+
},
|
1944
|
+
|
1945
|
+
/*
|
1946
|
+
* Add resizable capabilities to a calEvent
|
1947
|
+
*/
|
1948
|
+
_addResizableToCalEvent: function(calEvent, $calEvent, $weekDay) {
|
1949
|
+
var self = this;
|
1950
|
+
var options = this.options;
|
1951
|
+
$calEvent.resizable({
|
1952
|
+
grid: options.timeslotHeight,
|
1953
|
+
containment: $weekDay,
|
1954
|
+
handles: 's',
|
1955
|
+
minHeight: options.timeslotHeight,
|
1956
|
+
stop: function(event, ui) {
|
1957
|
+
var $calEvent = ui.element;
|
1958
|
+
var newEnd = new Date($calEvent.data('calEvent').start.getTime() + Math.max(1, Math.round(ui.size.height / options.timeslotHeight)) * options.millisPerTimeslot);
|
1959
|
+
if (self._needDSTdayShift($calEvent.data('calEvent').start, newEnd))
|
1960
|
+
newEnd = self._getDSTdayShift(newEnd, -1);
|
1961
|
+
var newCalEvent = $.extend(true, {}, calEvent, {start: calEvent.start, end: newEnd});
|
1962
|
+
self._adjustForEventCollisions($weekDay, $calEvent, newCalEvent, calEvent);
|
1963
|
+
|
1964
|
+
self._refreshEventDetails(newCalEvent, $calEvent);
|
1965
|
+
self._positionEvent($weekDay, $calEvent);
|
1966
|
+
self._adjustOverlappingEvents($weekDay);
|
1967
|
+
//trigger resize callback
|
1968
|
+
options.eventResize(newCalEvent, calEvent, $calEvent);
|
1969
|
+
$calEvent.data('preventClick', true);
|
1970
|
+
setTimeout(function() {
|
1971
|
+
$calEvent.removeData('preventClick');
|
1972
|
+
}, 500);
|
1973
|
+
}
|
1974
|
+
});
|
1975
|
+
$('.ui-resizable-handle', $calEvent).text('=');
|
1976
|
+
},
|
1977
|
+
|
1978
|
+
/*
|
1979
|
+
* Refresh the displayed details of a calEvent in the calendar
|
1980
|
+
*/
|
1981
|
+
_refreshEventDetails: function(calEvent, $calEvent) {
|
1982
|
+
var suffix = '';
|
1983
|
+
if (!this.options.readonly &&
|
1984
|
+
this.options.allowEventDelete &&
|
1985
|
+
this.options.deletable(calEvent,$calEvent)) {
|
1986
|
+
suffix = '<div class="wc-cal-event-delete ui-icon ui-icon-close"></div>';
|
1987
|
+
}
|
1988
|
+
$calEvent.find('.wc-time').html(this.options.eventHeader(calEvent, this.element) + suffix);
|
1989
|
+
$calEvent.find('.wc-title').html(this.options.eventBody(calEvent, this.element));
|
1990
|
+
$calEvent.data('calEvent', calEvent);
|
1991
|
+
this.options.eventRefresh(calEvent, $calEvent);
|
1992
|
+
},
|
1993
|
+
|
1994
|
+
/*
|
1995
|
+
* Clear all cal events from the calendar
|
1996
|
+
*/
|
1997
|
+
_clearCalendar: function() {
|
1998
|
+
this.element.find('.wc-day-column-inner div').remove();
|
1999
|
+
this._clearFreeBusys();
|
2000
|
+
},
|
2001
|
+
|
2002
|
+
/*
|
2003
|
+
* Scroll the calendar to a specific hour
|
2004
|
+
*/
|
2005
|
+
_scrollToHour: function(hour, animate) {
|
2006
|
+
var self = this;
|
2007
|
+
var options = this.options;
|
2008
|
+
var $scrollable = this.element.find('.wc-scrollable-grid');
|
2009
|
+
var slot = hour;
|
2010
|
+
if (self.options.businessHours.limitDisplay) {
|
2011
|
+
if (hour <= self.options.businessHours.start) {
|
2012
|
+
slot = 0;
|
2013
|
+
} else if (hour >= self.options.businessHours.end) {
|
2014
|
+
slot = self.options.businessHours.end - self.options.businessHours.start - 1;
|
2015
|
+
} else {
|
2016
|
+
slot = hour - self.options.businessHours.start;
|
2017
|
+
}
|
2018
|
+
}
|
2019
|
+
|
2020
|
+
var $target = this.element.find('.wc-grid-timeslot-header .wc-hour-header:eq(' + slot + ')');
|
2021
|
+
|
2022
|
+
$scrollable.animate({scrollTop: 0}, 0, function() {
|
2023
|
+
var targetOffset = $target.offset().top;
|
2024
|
+
var scroll = targetOffset - $scrollable.offset().top - $target.outerHeight();
|
2025
|
+
if (animate) {
|
2026
|
+
$scrollable.animate({scrollTop: scroll}, options.scrollToHourMillis);
|
2027
|
+
}
|
2028
|
+
else {
|
2029
|
+
$scrollable.animate({scrollTop: scroll}, 0);
|
2030
|
+
}
|
2031
|
+
});
|
2032
|
+
},
|
2033
|
+
|
2034
|
+
/*
|
2035
|
+
* find the hour (12 hour day) for a given hour index
|
2036
|
+
*/
|
2037
|
+
_hourForIndex: function(index) {
|
2038
|
+
if (index === 0) { //midnight
|
2039
|
+
return 12;
|
2040
|
+
} else if (index < 13) { //am
|
2041
|
+
return index;
|
2042
|
+
} else { //pm
|
2043
|
+
return index - 12;
|
2044
|
+
}
|
2045
|
+
},
|
2046
|
+
|
2047
|
+
_24HourForIndex: function(index) {
|
2048
|
+
if (index === 0) { //midnight
|
2049
|
+
return '00:00';
|
2050
|
+
} else if (index < 10) {
|
2051
|
+
return '0' + index + ':00';
|
2052
|
+
} else {
|
2053
|
+
return index + ':00';
|
2054
|
+
}
|
2055
|
+
},
|
2056
|
+
|
2057
|
+
_amOrPm: function(hourOfDay) {
|
2058
|
+
return hourOfDay < 12 ? 'AM' : 'PM';
|
2059
|
+
},
|
2060
|
+
|
2061
|
+
_isToday: function(date) {
|
2062
|
+
var clonedDate = this._cloneDate(date);
|
2063
|
+
this._clearTime(clonedDate);
|
2064
|
+
var today = new Date();
|
2065
|
+
this._clearTime(today);
|
2066
|
+
return today.getTime() === clonedDate.getTime();
|
2067
|
+
},
|
2068
|
+
|
2069
|
+
/*
|
2070
|
+
* Clean events to ensure correct format
|
2071
|
+
*/
|
2072
|
+
_cleanEvents: function(events) {
|
2073
|
+
var self = this;
|
2074
|
+
$.each(events, function(i, event) {
|
2075
|
+
self._cleanEvent(event);
|
2076
|
+
});
|
2077
|
+
return events;
|
2078
|
+
},
|
2079
|
+
|
2080
|
+
/*
|
2081
|
+
* Clean specific event
|
2082
|
+
*/
|
2083
|
+
_cleanEvent: function(event) {
|
2084
|
+
if (event.date) {
|
2085
|
+
event.start = event.date;
|
2086
|
+
}
|
2087
|
+
event.start = this._cleanDate(event.start);
|
2088
|
+
event.end = this._cleanDate(event.end);
|
2089
|
+
if (!event.end) {
|
2090
|
+
event.end = this._addDays(this._cloneDate(event.start), 1);
|
2091
|
+
}
|
2092
|
+
},
|
2093
|
+
|
2094
|
+
/*
|
2095
|
+
* Disable text selection of the elements in different browsers
|
2096
|
+
*/
|
2097
|
+
_disableTextSelect: function($elements) {
|
2098
|
+
$elements.each(function() {
|
2099
|
+
if ($.browser.mozilla) {//Firefox
|
2100
|
+
$(this).css('MozUserSelect', 'none');
|
2101
|
+
} else if ($.browser.msie) {//IE
|
2102
|
+
$(this).bind('selectstart', function() {
|
2103
|
+
return false;
|
2104
|
+
});
|
2105
|
+
} else {//Opera, etc.
|
2106
|
+
$(this).mousedown(function() {
|
2107
|
+
return false;
|
2108
|
+
});
|
2109
|
+
}
|
2110
|
+
});
|
2111
|
+
},
|
2112
|
+
|
2113
|
+
/*
|
2114
|
+
* returns the date on the first millisecond of the week
|
2115
|
+
*/
|
2116
|
+
_dateFirstDayOfWeek: function(date) {
|
2117
|
+
var self = this;
|
2118
|
+
var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
2119
|
+
var adjustedDate = new Date(midnightCurrentDate);
|
2120
|
+
adjustedDate.setDate(adjustedDate.getDate() - self._getAdjustedDayIndex(midnightCurrentDate));
|
2121
|
+
|
2122
|
+
return adjustedDate;
|
2123
|
+
},
|
2124
|
+
|
2125
|
+
/*
|
2126
|
+
* returns the date on the first millisecond of the last day of the week
|
2127
|
+
*/
|
2128
|
+
_dateLastDayOfWeek: function(date) {
|
2129
|
+
var self = this;
|
2130
|
+
var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
2131
|
+
var adjustedDate = new Date(midnightCurrentDate);
|
2132
|
+
var daysToAdd = (self.options.daysToShow - 1 - self._getAdjustedDayIndex(midnightCurrentDate));
|
2133
|
+
adjustedDate.setDate(adjustedDate.getDate() + daysToAdd);
|
2134
|
+
|
2135
|
+
return adjustedDate;
|
2136
|
+
},
|
2137
|
+
|
2138
|
+
/**
|
2139
|
+
* fix the date if it is not within given options
|
2140
|
+
* minDate and maxDate
|
2141
|
+
*/
|
2142
|
+
_fixMinMaxDate: function(date) {
|
2143
|
+
var minDate, maxDate;
|
2144
|
+
date = this._cleanDate(date);
|
2145
|
+
|
2146
|
+
// not less than minDate
|
2147
|
+
if (this.options.minDate) {
|
2148
|
+
minDate = this._cleanDate(this.options.minDate);
|
2149
|
+
// midnight on minDate
|
2150
|
+
minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
|
2151
|
+
if (date.getTime() < minDate.getTime()) {
|
2152
|
+
this._trigger('reachedmindate', this.element, date);
|
2153
|
+
}
|
2154
|
+
date = this._cleanDate(Math.max(date.getTime(), minDate.getTime()));
|
2155
|
+
}
|
2156
|
+
|
2157
|
+
// not more than maxDate
|
2158
|
+
if (this.options.maxDate) {
|
2159
|
+
maxDate = this._cleanDate(this.options.maxDate);
|
2160
|
+
// apply correction for max date if not startOnFirstDayOfWeek
|
2161
|
+
// to make sure no further date is displayed.
|
2162
|
+
// otherwise, the complement will still be shown
|
2163
|
+
if (!this._startOnFirstDayOfWeek()) {
|
2164
|
+
var day = maxDate.getDate() - this.options.daysToShow + 1;
|
2165
|
+
maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), day);
|
2166
|
+
}
|
2167
|
+
// microsecond before midnight on maxDate
|
2168
|
+
maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999);
|
2169
|
+
if (date.getTime() > maxDate.getTime()) {
|
2170
|
+
this._trigger('reachedmaxdate', this.element, date);
|
2171
|
+
}
|
2172
|
+
date = this._cleanDate(Math.min(date.getTime(), maxDate.getTime()));
|
2173
|
+
}
|
2174
|
+
|
2175
|
+
return date;
|
2176
|
+
},
|
2177
|
+
|
2178
|
+
/*
|
2179
|
+
* gets the index of the current day adjusted based on options
|
2180
|
+
*/
|
2181
|
+
_getAdjustedDayIndex: function(date) {
|
2182
|
+
if (!this._startOnFirstDayOfWeek()) {
|
2183
|
+
return 0;
|
2184
|
+
}
|
2185
|
+
|
2186
|
+
var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
2187
|
+
var currentDayOfStandardWeek = midnightCurrentDate.getDay();
|
2188
|
+
var days = [0, 1, 2, 3, 4, 5, 6];
|
2189
|
+
this._rotate(days, this._firstDayOfWeek());
|
2190
|
+
return days[currentDayOfStandardWeek];
|
2191
|
+
},
|
2192
|
+
|
2193
|
+
_firstDayOfWeek: function() {
|
2194
|
+
if ($.isFunction(this.options.firstDayOfWeek)) {
|
2195
|
+
return this.options.firstDayOfWeek(this.element);
|
2196
|
+
}
|
2197
|
+
return this.options.firstDayOfWeek;
|
2198
|
+
},
|
2199
|
+
|
2200
|
+
/*
|
2201
|
+
* returns the date on the last millisecond of the week
|
2202
|
+
*/
|
2203
|
+
_dateLastMilliOfWeek: function(date) {
|
2204
|
+
var lastDayOfWeek = this._dateLastDayOfWeek(date);
|
2205
|
+
lastDayOfWeek = this._cloneDate(lastDayOfWeek);
|
2206
|
+
lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 1);
|
2207
|
+
return lastDayOfWeek;
|
2208
|
+
|
2209
|
+
},
|
2210
|
+
|
2211
|
+
/*
|
2212
|
+
* Clear the time components of a date leaving the date
|
2213
|
+
* of the first milli of day
|
2214
|
+
*/
|
2215
|
+
_clearTime: function(d) {
|
2216
|
+
d.setHours(0);
|
2217
|
+
d.setMinutes(0);
|
2218
|
+
d.setSeconds(0);
|
2219
|
+
d.setMilliseconds(0);
|
2220
|
+
return d;
|
2221
|
+
},
|
2222
|
+
|
2223
|
+
/*
|
2224
|
+
* add specific number of days to date
|
2225
|
+
*/
|
2226
|
+
_addDays: function(d, n, keepTime) {
|
2227
|
+
d.setDate(d.getDate() + n);
|
2228
|
+
if (keepTime) {
|
2229
|
+
return d;
|
2230
|
+
}
|
2231
|
+
return this._clearTime(d);
|
2232
|
+
},
|
2233
|
+
|
2234
|
+
/*
|
2235
|
+
* Rotate an array by specified number of places.
|
2236
|
+
*/
|
2237
|
+
_rotate: function(a /*array*/, p /* integer, positive integer rotate to the right, negative to the left... */) {
|
2238
|
+
for (var l = a.length, p = (Math.abs(p) >= l && (p %= l), p < 0 && (p += l), p), i, x; p; p = (Math.ceil(l / p) - 1) * p - l + (l = p)) {
|
2239
|
+
for (i = l; i > p; x = a[--i], a[i] = a[i - p], a[i - p] = x) {}
|
2240
|
+
}
|
2241
|
+
return a;
|
2242
|
+
},
|
2243
|
+
|
2244
|
+
_cloneDate: function(d) {
|
2245
|
+
return new Date(d.getTime());
|
2246
|
+
},
|
2247
|
+
|
2248
|
+
/*
|
2249
|
+
* return a date for different representations
|
2250
|
+
*/
|
2251
|
+
_cleanDate: function(d) {
|
2252
|
+
if (typeof d == 'string') {
|
2253
|
+
// if is numeric
|
2254
|
+
if (!isNaN(parseFloat(d)) && isFinite()) {
|
2255
|
+
return this._cleanDate(parseInt(d, 10));
|
2256
|
+
}
|
2257
|
+
// this is a human readable date
|
2258
|
+
return Date.parse(d) || new Date(d);
|
2259
|
+
}
|
2260
|
+
if (typeof d == 'number') {
|
2261
|
+
return new Date(d);
|
2262
|
+
}
|
2263
|
+
return d;
|
2264
|
+
},
|
2265
|
+
|
2266
|
+
/*
|
2267
|
+
* date formatting is adapted from
|
2268
|
+
* http://jacwright.com/projects/javascript/date_format
|
2269
|
+
*/
|
2270
|
+
_formatDate: function(date, format) {
|
2271
|
+
var returnStr = '';
|
2272
|
+
for (var i = 0; i < format.length; i++) {
|
2273
|
+
var curChar = format.charAt(i);
|
2274
|
+
if (i != 0 && format.charAt(i - 1) == '\\') {
|
2275
|
+
returnStr += curChar;
|
2276
|
+
}
|
2277
|
+
else if (this._replaceChars[curChar]) {
|
2278
|
+
returnStr += this._replaceChars[curChar](date, this);
|
2279
|
+
} else if (curChar != '\\') {
|
2280
|
+
returnStr += curChar;
|
2281
|
+
}
|
2282
|
+
}
|
2283
|
+
return returnStr;
|
2284
|
+
},
|
2285
|
+
|
2286
|
+
_replaceChars: {
|
2287
|
+
// Day
|
2288
|
+
d: function(date) { return (date.getDate() < 10 ? '0' : '') + date.getDate(); },
|
2289
|
+
D: function(date, calendar) { return calendar.options.shortDays[date.getDay()]; },
|
2290
|
+
j: function(date) { return date.getDate(); },
|
2291
|
+
l: function(date, calendar) { return calendar.options.longDays[date.getDay()]; },
|
2292
|
+
N: function(date) { var _d = date.getDay(); return _d ? _d : 7; },
|
2293
|
+
S: function(date) { return (date.getDate() % 10 == 1 && date.getDate() != 11 ? 'st' : (date.getDate() % 10 == 2 && date.getDate() != 12 ? 'nd' : (date.getDate() % 10 == 3 && date.getDate() != 13 ? 'rd' : 'th'))); },
|
2294
|
+
w: function(date) { return date.getDay(); },
|
2295
|
+
z: function(date) { var d = new Date(date.getFullYear(), 0, 1); return Math.ceil((date - d) / 86400000); }, // Fixed now
|
2296
|
+
// Week
|
2297
|
+
W: function(date) { var d = new Date(date.getFullYear(), 0, 1); return Math.ceil((((date - d) / 86400000) + d.getDay() + 1) / 7); }, // Fixed now
|
2298
|
+
// Month
|
2299
|
+
F: function(date, calendar) { return calendar.options.longMonths[date.getMonth()]; },
|
2300
|
+
m: function(date) { return (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1); },
|
2301
|
+
M: function(date, calendar) { return calendar.options.shortMonths[date.getMonth()]; },
|
2302
|
+
n: function(date) { return date.getMonth() + 1; },
|
2303
|
+
t: function(date) { var d = date; return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate() }, // Fixed now, gets #days of date
|
2304
|
+
// Year
|
2305
|
+
L: function(date) { var year = date.getFullYear(); return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)); }, // Fixed now
|
2306
|
+
o: function(date) { var d = new Date(date.valueOf()); d.setDate(d.getDate() - ((date.getDay() + 6) % 7) + 3); return d.getFullYear();}, //Fixed now
|
2307
|
+
Y: function(date) { return date.getFullYear(); },
|
2308
|
+
y: function(date) { return ('' + date.getFullYear()).substr(2); },
|
2309
|
+
// Time
|
2310
|
+
a: function(date) { return date.getHours() < 12 ? 'am' : 'pm'; },
|
2311
|
+
A: function(date) { return date.getHours() < 12 ? 'AM' : 'PM'; },
|
2312
|
+
B: function(date) { return Math.floor((((date.getUTCHours() + 1) % 24) + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600) * 1000 / 24); }, // Fixed now
|
2313
|
+
g: function(date) { return date.getHours() % 12 || 12; },
|
2314
|
+
G: function(date) { return date.getHours(); },
|
2315
|
+
h: function(date) { return ((date.getHours() % 12 || 12) < 10 ? '0' : '') + (date.getHours() % 12 || 12); },
|
2316
|
+
H: function(date) { return (date.getHours() < 10 ? '0' : '') + date.getHours(); },
|
2317
|
+
i: function(date) { return (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); },
|
2318
|
+
s: function(date) { return (date.getSeconds() < 10 ? '0' : '') + date.getSeconds(); },
|
2319
|
+
u: function(date) { var m = date.getMilliseconds(); return (m < 10 ? '00' : (m < 100 ? '0' : '')) + m; },
|
2320
|
+
// Timezone
|
2321
|
+
e: function(date) { return 'Not Yet Supported'; },
|
2322
|
+
I: function(date) { return 'Not Yet Supported'; },
|
2323
|
+
O: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + '00'; },
|
2324
|
+
P: function(date) { return (-date.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(date.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(date.getTimezoneOffset() / 60)) + ':00'; }, // Fixed now
|
2325
|
+
T: function(date) { var m = date.getMonth(); date.setMonth(0); var result = date.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); date.setMonth(m); return result;},
|
2326
|
+
Z: function(date) { return -date.getTimezoneOffset() * 60; },
|
2327
|
+
// Full Date/Time
|
2328
|
+
c: function(date, calendar) { return calendar._formatDate(date, 'Y-m-d\\TH:i:sP'); }, // Fixed now
|
2329
|
+
r: function(date, calendar) { return calendar._formatDate(date, 'D, d M Y H:i:s O'); },
|
2330
|
+
U: function(date) { return date.getTime() / 1000; }
|
2331
|
+
},
|
2332
|
+
|
2333
|
+
/* USER MANAGEMENT FUNCTIONS */
|
2334
|
+
|
2335
|
+
getUserForId: function(id) {
|
2336
|
+
return $.extend({}, this.options.users[this._getUserIndexFromId(id)]);
|
2337
|
+
},
|
2338
|
+
|
2339
|
+
/**
|
2340
|
+
* return the user name for header
|
2341
|
+
*/
|
2342
|
+
_getUserName: function(index) {
|
2343
|
+
var self = this;
|
2344
|
+
var options = this.options;
|
2345
|
+
var user = options.users[index];
|
2346
|
+
if ($.isFunction(options.getUserName)) {
|
2347
|
+
return options.getUserName(user, index, self.element);
|
2348
|
+
}
|
2349
|
+
else {
|
2350
|
+
return user;
|
2351
|
+
}
|
2352
|
+
},
|
2353
|
+
/**
|
2354
|
+
* return the user id for given index
|
2355
|
+
*/
|
2356
|
+
_getUserIdFromIndex: function(index) {
|
2357
|
+
var self = this;
|
2358
|
+
var options = this.options;
|
2359
|
+
if ($.isFunction(options.getUserId)) {
|
2360
|
+
return options.getUserId(options.users[index], index, self.element);
|
2361
|
+
}
|
2362
|
+
return index;
|
2363
|
+
},
|
2364
|
+
/**
|
2365
|
+
* returns the associated user index for given ID
|
2366
|
+
*/
|
2367
|
+
_getUserIndexFromId: function(id) {
|
2368
|
+
var self = this;
|
2369
|
+
var options = this.options;
|
2370
|
+
for (var i = 0; i < options.users.length; i++) {
|
2371
|
+
if (self._getUserIdFromIndex(i) == id) {
|
2372
|
+
return i;
|
2373
|
+
}
|
2374
|
+
}
|
2375
|
+
return 0;
|
2376
|
+
},
|
2377
|
+
/**
|
2378
|
+
* return the user ids for given calEvent.
|
2379
|
+
* default is calEvent.userId field.
|
2380
|
+
*/
|
2381
|
+
_getEventUserId: function(calEvent) {
|
2382
|
+
var self = this;
|
2383
|
+
var options = this.options;
|
2384
|
+
if (options.showAsSeparateUsers && options.users && options.users.length) {
|
2385
|
+
if ($.isFunction(options.getEventUserId)) {
|
2386
|
+
return options.getEventUserId(calEvent, self.element);
|
2387
|
+
}
|
2388
|
+
return calEvent.userId;
|
2389
|
+
}
|
2390
|
+
return [];
|
2391
|
+
},
|
2392
|
+
/**
|
2393
|
+
* sets the event user id on given calEvent
|
2394
|
+
* default is calEvent.userId field.
|
2395
|
+
*/
|
2396
|
+
_setEventUserId: function(calEvent, userId) {
|
2397
|
+
var self = this;
|
2398
|
+
var options = this.options;
|
2399
|
+
if ($.isFunction(options.setEventUserId)) {
|
2400
|
+
return options.setEventUserId(userId, calEvent, self.element);
|
2401
|
+
}
|
2402
|
+
calEvent.userId = userId;
|
2403
|
+
return calEvent;
|
2404
|
+
},
|
2405
|
+
/**
|
2406
|
+
* return the user ids for given freeBusy.
|
2407
|
+
* default is freeBusy.userId field.
|
2408
|
+
*/
|
2409
|
+
_getFreeBusyUserId: function(freeBusy) {
|
2410
|
+
var self = this;
|
2411
|
+
var options = this.options;
|
2412
|
+
if ($.isFunction(options.getFreeBusyUserId)) {
|
2413
|
+
return options.getFreeBusyUserId(freeBusy.getOption(), self.element);
|
2414
|
+
}
|
2415
|
+
return freeBusy.getOption('userId');
|
2416
|
+
},
|
2417
|
+
|
2418
|
+
/* FREEBUSY MANAGEMENT */
|
2419
|
+
|
2420
|
+
/**
|
2421
|
+
* ckean the free busy managers and remove all the freeBusy
|
2422
|
+
*/
|
2423
|
+
_clearFreeBusys: function() {
|
2424
|
+
if (this.options.displayFreeBusys) {
|
2425
|
+
var self = this,
|
2426
|
+
options = this.options,
|
2427
|
+
$freeBusyPlaceholders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy');
|
2428
|
+
$freeBusyPlaceholders.each(function() {
|
2429
|
+
$(this).data('wcFreeBusyManager', new FreeBusyManager({
|
2430
|
+
start: self._cloneDate($(this).data('startDate')),
|
2431
|
+
end: self._cloneDate($(this).data('endDate')),
|
2432
|
+
defaultFreeBusy: options.defaultFreeBusy || {}
|
2433
|
+
}));
|
2434
|
+
});
|
2435
|
+
self.element.find('.wc-grid-row-freebusy .wc-freebusy').remove();
|
2436
|
+
}
|
2437
|
+
},
|
2438
|
+
/**
|
2439
|
+
* retrieve placeholders for given freebusy
|
2440
|
+
*/
|
2441
|
+
_findWeekDaysForFreeBusy: function(freeBusy, $weekDays) {
|
2442
|
+
var $returnWeekDays,
|
2443
|
+
options = this.options,
|
2444
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
2445
|
+
self = this,
|
2446
|
+
userList = self._getFreeBusyUserId(freeBusy);
|
2447
|
+
if (!$.isArray(userList)) {
|
2448
|
+
userList = userList != 'undefined' ? [userList] : [];
|
2449
|
+
}
|
2450
|
+
if (!$weekDays) {
|
2451
|
+
$weekDays = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy');
|
2452
|
+
}
|
2453
|
+
$weekDays.each(function() {
|
2454
|
+
var manager = $(this).data('wcFreeBusyManager'),
|
2455
|
+
has_overlap = manager.isWithin(freeBusy.getStart()) ||
|
2456
|
+
manager.isWithin(freeBusy.getEnd()) ||
|
2457
|
+
freeBusy.isWithin(manager.getStart()) ||
|
2458
|
+
freeBusy.isWithin(manager.getEnd()),
|
2459
|
+
userId = $(this).data('wcUserId');
|
2460
|
+
if (has_overlap && (!showAsSeparatedUser || ($.inArray(userId, userList) != -1))) {
|
2461
|
+
$returnWeekDays = $returnWeekDays ? $returnWeekDays.add($(this)) : $(this);
|
2462
|
+
}
|
2463
|
+
});
|
2464
|
+
return $returnWeekDays;
|
2465
|
+
},
|
2466
|
+
|
2467
|
+
/**
|
2468
|
+
* used to render all freeBusys
|
2469
|
+
*/
|
2470
|
+
_renderFreeBusys: function(freeBusys) {
|
2471
|
+
if (this.options.displayFreeBusys) {
|
2472
|
+
var self = this,
|
2473
|
+
$freeBusyPlaceholders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
|
2474
|
+
freebusysToRender;
|
2475
|
+
//insert freebusys to dedicated placeholders freebusy managers
|
2476
|
+
if ($.isArray(freeBusys)) {
|
2477
|
+
freebusysToRender = self._cleanFreeBusys(freeBusys);
|
2478
|
+
} else if (freeBusys.freebusys) {
|
2479
|
+
freebusysToRender = self._cleanFreeBusys(freeBusys.freebusys);
|
2480
|
+
}
|
2481
|
+
else {
|
2482
|
+
freebusysToRender = [];
|
2483
|
+
}
|
2484
|
+
|
2485
|
+
$.each(freebusysToRender, function(index, freebusy) {
|
2486
|
+
var $placeholders = self._findWeekDaysForFreeBusy(freebusy, $freeBusyPlaceholders);
|
2487
|
+
if ($placeholders) {
|
2488
|
+
$placeholders.each(function() {
|
2489
|
+
var manager = $(this).data('wcFreeBusyManager');
|
2490
|
+
manager.insertFreeBusy(new FreeBusy(freebusy.getOption()));
|
2491
|
+
$(this).data('wcFreeBusyManager', manager);
|
2492
|
+
});
|
2493
|
+
}
|
2494
|
+
});
|
2495
|
+
|
2496
|
+
//now display freebusys on place holders
|
2497
|
+
self._refreshFreeBusys($freeBusyPlaceholders);
|
2498
|
+
}
|
2499
|
+
},
|
2500
|
+
/**
|
2501
|
+
* refresh freebusys for given placeholders
|
2502
|
+
*/
|
2503
|
+
_refreshFreeBusys: function($freeBusyPlaceholders) {
|
2504
|
+
if (this.options.displayFreeBusys && $freeBusyPlaceholders) {
|
2505
|
+
var self = this,
|
2506
|
+
options = this.options,
|
2507
|
+
start = (options.businessHours.limitDisplay ? options.businessHours.start : 0),
|
2508
|
+
end = (options.businessHours.limitDisplay ? options.businessHours.end : 24);
|
2509
|
+
|
2510
|
+
$freeBusyPlaceholders.each(function() {
|
2511
|
+
var $placehoder = $(this);
|
2512
|
+
var s = self._cloneDate($placehoder.data('startDate')),
|
2513
|
+
e = self._cloneDate(s);
|
2514
|
+
s.setHours(start);
|
2515
|
+
e.setHours(end);
|
2516
|
+
$placehoder.find('.wc-freebusy').remove();
|
2517
|
+
$.each($placehoder.data('wcFreeBusyManager').getFreeBusys(s, e), function() {
|
2518
|
+
self._renderFreeBusy(this, $placehoder);
|
2519
|
+
});
|
2520
|
+
});
|
2521
|
+
}
|
2522
|
+
},
|
2523
|
+
/**
|
2524
|
+
* render a freebusy item on dedicated placeholders
|
2525
|
+
*/
|
2526
|
+
_renderFreeBusy: function(freeBusy, $freeBusyPlaceholder) {
|
2527
|
+
if (this.options.displayFreeBusys) {
|
2528
|
+
var self = this,
|
2529
|
+
options = this.options,
|
2530
|
+
freeBusyHtml = '<div class="wc-freebusy"></div>';
|
2531
|
+
|
2532
|
+
var $fb = $(freeBusyHtml);
|
2533
|
+
$fb.data('wcFreeBusy', new FreeBusy(freeBusy.getOption()));
|
2534
|
+
this._positionFreeBusy($freeBusyPlaceholder, $fb);
|
2535
|
+
$fb = options.freeBusyRender(freeBusy.getOption(), $fb, self.element);
|
2536
|
+
if ($fb) {
|
2537
|
+
$fb.appendTo($freeBusyPlaceholder);
|
2538
|
+
}
|
2539
|
+
}
|
2540
|
+
},
|
2541
|
+
/*
|
2542
|
+
* Position the freebusy element within the weekday based on it's start / end dates.
|
2543
|
+
*/
|
2544
|
+
_positionFreeBusy: function($placeholder, $freeBusy) {
|
2545
|
+
var options = this.options;
|
2546
|
+
var freeBusy = $freeBusy.data('wcFreeBusy');
|
2547
|
+
var pxPerMillis = $placeholder.height() / options.millisToDisplay;
|
2548
|
+
var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0;
|
2549
|
+
var startMillis = freeBusy.getStart().getTime() - new Date(freeBusy.getStart().getFullYear(), freeBusy.getStart().getMonth(), freeBusy.getStart().getDate(), firstHourDisplayed).getTime();
|
2550
|
+
var eventMillis = freeBusy.getEnd().getTime() - freeBusy.getStart().getTime();
|
2551
|
+
var pxTop = pxPerMillis * startMillis;
|
2552
|
+
var pxHeight = pxPerMillis * eventMillis;
|
2553
|
+
$freeBusy.css({top: pxTop, height: pxHeight});
|
2554
|
+
},
|
2555
|
+
/*
|
2556
|
+
* Clean freebusys to ensure correct format
|
2557
|
+
*/
|
2558
|
+
_cleanFreeBusys: function(freebusys) {
|
2559
|
+
var self = this,
|
2560
|
+
freeBusyToReturn = [];
|
2561
|
+
if (!$.isArray(freebusys)) {
|
2562
|
+
var freebusys = [freebusys];
|
2563
|
+
}
|
2564
|
+
$.each(freebusys, function(i, freebusy) {
|
2565
|
+
freeBusyToReturn.push(new FreeBusy(self._cleanFreeBusy(freebusy)));
|
2566
|
+
});
|
2567
|
+
return freeBusyToReturn;
|
2568
|
+
},
|
2569
|
+
|
2570
|
+
/*
|
2571
|
+
* Clean specific freebusy
|
2572
|
+
*/
|
2573
|
+
_cleanFreeBusy: function(freebusy) {
|
2574
|
+
if (freebusy.date) {
|
2575
|
+
freebusy.start = freebusy.date;
|
2576
|
+
}
|
2577
|
+
freebusy.start = this._cleanDate(freebusy.start);
|
2578
|
+
freebusy.end = this._cleanDate(freebusy.end);
|
2579
|
+
return freebusy;
|
2580
|
+
},
|
2581
|
+
|
2582
|
+
/**
|
2583
|
+
* retrives the first freebusy manager matching demand.
|
2584
|
+
*/
|
2585
|
+
getFreeBusyManagersFor: function(date, users) {
|
2586
|
+
var calEvent = {
|
2587
|
+
start: date,
|
2588
|
+
end: date
|
2589
|
+
};
|
2590
|
+
this._setEventUserId(calEvent, users);
|
2591
|
+
return this.getFreeBusyManagerForEvent(calEvent);
|
2592
|
+
},
|
2593
|
+
/**
|
2594
|
+
* retrives the first freebusy manager for given event.
|
2595
|
+
*/
|
2596
|
+
getFreeBusyManagerForEvent: function(newCalEvent) {
|
2597
|
+
var self = this,
|
2598
|
+
options = this.options,
|
2599
|
+
freeBusyManager;
|
2600
|
+
if (options.displayFreeBusys) {
|
2601
|
+
var $freeBusyPlaceHoders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
|
2602
|
+
freeBusy = new FreeBusy({start: newCalEvent.start, end: newCalEvent.end}),
|
2603
|
+
showAsSeparatedUser = options.showAsSeparateUsers && options.users && options.users.length,
|
2604
|
+
userId = showAsSeparatedUser ? self._getEventUserId(newCalEvent) : null;
|
2605
|
+
if (!$.isArray(userId)) {
|
2606
|
+
userId = [userId];
|
2607
|
+
}
|
2608
|
+
$freeBusyPlaceHoders.each(function() {
|
2609
|
+
var manager = $(this).data('wcFreeBusyManager'),
|
2610
|
+
has_overlap = manager.isWithin(freeBusy.getEnd()) ||
|
2611
|
+
manager.isWithin(freeBusy.getEnd()) ||
|
2612
|
+
freeBusy.isWithin(manager.getStart()) ||
|
2613
|
+
freeBusy.isWithin(manager.getEnd());
|
2614
|
+
if (has_overlap && (!showAsSeparatedUser || $.inArray($(this).data('wcUserId'), userId) != -1)) {
|
2615
|
+
freeBusyManager = $(this).data('wcFreeBusyManager');
|
2616
|
+
return false;
|
2617
|
+
}
|
2618
|
+
});
|
2619
|
+
}
|
2620
|
+
return freeBusyManager;
|
2621
|
+
},
|
2622
|
+
/**
|
2623
|
+
* appends the freebusys to replace the old ones.
|
2624
|
+
* @param {array|object} freeBusys freebusy(s) to apply.
|
2625
|
+
*/
|
2626
|
+
updateFreeBusy: function(freeBusys) {
|
2627
|
+
var self = this,
|
2628
|
+
options = this.options;
|
2629
|
+
if (options.displayFreeBusys) {
|
2630
|
+
var $toRender,
|
2631
|
+
$freeBusyPlaceHoders = self.element.find('.wc-grid-row-freebusy .wc-column-freebusy'),
|
2632
|
+
_freeBusys = self._cleanFreeBusys(freeBusys);
|
2633
|
+
|
2634
|
+
$.each(_freeBusys, function(index, _freeBusy) {
|
2635
|
+
|
2636
|
+
var $weekdays = self._findWeekDaysForFreeBusy(_freeBusy, $freeBusyPlaceHoders);
|
2637
|
+
//if freebusy has a placeholder
|
2638
|
+
if ($weekdays && $weekdays.length) {
|
2639
|
+
$weekdays.each(function(index, day) {
|
2640
|
+
var manager = $(day).data('wcFreeBusyManager');
|
2641
|
+
manager.insertFreeBusy(_freeBusy);
|
2642
|
+
$(day).data('wcFreeBusyManager', manager);
|
2643
|
+
});
|
2644
|
+
$toRender = $toRender ? $toRender.add($weekdays) : $weekdays;
|
2645
|
+
}
|
2646
|
+
});
|
2647
|
+
self._refreshFreeBusys($toRender);
|
2648
|
+
}
|
2649
|
+
},
|
2650
|
+
|
2651
|
+
/* NEW OPTIONS MANAGEMENT */
|
2652
|
+
|
2653
|
+
/**
|
2654
|
+
* checks wether or not the calendar should be displayed starting on first day of week
|
2655
|
+
*/
|
2656
|
+
_startOnFirstDayOfWeek: function() {
|
2657
|
+
return jQuery.isFunction(this.options.startOnFirstDayOfWeek) ? this.options.startOnFirstDayOfWeek(this.element) : this.options.startOnFirstDayOfWeek;
|
2658
|
+
},
|
2659
|
+
|
2660
|
+
/**
|
2661
|
+
* finds out the current scroll to apply it when changing the view
|
2662
|
+
*/
|
2663
|
+
_getCurrentScrollHour: function() {
|
2664
|
+
var self = this;
|
2665
|
+
var options = this.options;
|
2666
|
+
var $scrollable = this.element.find('.wc-scrollable-grid');
|
2667
|
+
var scroll = $scrollable.scrollTop();
|
2668
|
+
if (self.options.businessHours.limitDisplay) {
|
2669
|
+
scroll = scroll + options.businessHours.start * options.timeslotHeight * options.timeslotsPerHour;
|
2670
|
+
}
|
2671
|
+
return Math.round(scroll / (options.timeslotHeight * options.timeslotsPerHour)) + 1;
|
2672
|
+
},
|
2673
|
+
_getJsonOptions: function() {
|
2674
|
+
if ($.isFunction(this.options.jsonOptions)) {
|
2675
|
+
return $.extend({}, this.options.jsonOptions(this.element));
|
2676
|
+
}
|
2677
|
+
if ($.isPlainObject(this.options.jsonOptions)) {
|
2678
|
+
return $.extend({}, this.options.jsonOptions);
|
2679
|
+
}
|
2680
|
+
return {};
|
2681
|
+
},
|
2682
|
+
_getHeaderDate: function(date) {
|
2683
|
+
var options = this.options;
|
2684
|
+
if (options.getHeaderDate && $.isFunction(options.getHeaderDate))
|
2685
|
+
{
|
2686
|
+
return options.getHeaderDate(date, this.element);
|
2687
|
+
}
|
2688
|
+
var dayName = options.useShortDayNames ? options.shortDays[date.getDay()] : options.longDays[date.getDay()];
|
2689
|
+
return dayName + (options.headerSeparator) + this._formatDate(date, options.dateFormat);
|
2690
|
+
},
|
2691
|
+
|
2692
|
+
|
2693
|
+
|
2694
|
+
/**
|
2695
|
+
* returns corrected date related to DST problem
|
2696
|
+
*/
|
2697
|
+
_getDSTdayShift: function(date, shift) {
|
2698
|
+
var start = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0);
|
2699
|
+
var offset1 = start.getTimezoneOffset();
|
2700
|
+
var offset2 = date.getTimezoneOffset();
|
2701
|
+
if (offset1 == offset2)
|
2702
|
+
return date;
|
2703
|
+
shift = shift ? shift : 1;
|
2704
|
+
return new Date(date.getTime() - shift * (offset1 > offset2 ? -1 : 1) * (Math.max(offset1, offset2) - Math.min(offset1, offset2)) * 60000);
|
2705
|
+
},
|
2706
|
+
_needDSTdayShift: function(date1, date2) {
|
2707
|
+
return date1.getTimezoneOffset() != date2.getTimezoneOffset();
|
2708
|
+
}
|
2709
|
+
|
2710
|
+
|
2711
|
+
|
2712
|
+
}; // end of widget function return
|
2713
|
+
})() //end of widget function closure execution
|
2714
|
+
); // end of $.widget("ui.weekCalendar"...
|
2715
|
+
|
2716
|
+
$.extend($.ui.weekCalendar, {
|
2717
|
+
version: '2.0-dev',
|
2718
|
+
updateLayoutOptions: {
|
2719
|
+
startOnFirstDayOfWeek: true,
|
2720
|
+
firstDayOfWeek: true,
|
2721
|
+
daysToShow: true,
|
2722
|
+
displayOddEven: true,
|
2723
|
+
timeFormat: true,
|
2724
|
+
dateFormat: true,
|
2725
|
+
use24Hour: true,
|
2726
|
+
useShortDayNames: true,
|
2727
|
+
businessHours: true,
|
2728
|
+
timeslotHeight: true,
|
2729
|
+
timeslotsPerHour: true,
|
2730
|
+
buttonText: true,
|
2731
|
+
height: true,
|
2732
|
+
shortMonths: true,
|
2733
|
+
longMonths: true,
|
2734
|
+
shortDays: true,
|
2735
|
+
longDays: true,
|
2736
|
+
textSize: true,
|
2737
|
+
users: true,
|
2738
|
+
showAsSeparateUsers: true,
|
2739
|
+
displayFreeBusys: true
|
2740
|
+
}
|
2741
|
+
});
|
2742
|
+
|
2743
|
+
var MILLIS_IN_DAY = 86400000;
|
2744
|
+
var MILLIS_IN_WEEK = MILLIS_IN_DAY * 7;
|
2745
|
+
|
2746
|
+
/* FREE BUSY MANAGERS */
|
2747
|
+
var FreeBusyProto = {
|
2748
|
+
getStart: function() {return this.getOption('start')},
|
2749
|
+
getEnd: function() {return this.getOption('end')},
|
2750
|
+
getOption: function() {
|
2751
|
+
if (!arguments.length) { return this.options }
|
2752
|
+
if (typeof(this.options[arguments[0]]) !== 'undefined') {
|
2753
|
+
return this.options[arguments[0]];
|
2754
|
+
}
|
2755
|
+
else if (typeof(arguments[1]) !== 'undefined') {
|
2756
|
+
return arguments[1];
|
2757
|
+
}
|
2758
|
+
return null;
|
2759
|
+
},
|
2760
|
+
setOption: function(key, value) {
|
2761
|
+
if (arguments.length == 1) {
|
2762
|
+
$.extend(this.options, arguments[0]);
|
2763
|
+
return this;
|
2764
|
+
}
|
2765
|
+
this.options[key] = value;
|
2766
|
+
return this;
|
2767
|
+
},
|
2768
|
+
isWithin: function(dateTime) {return Math.floor(dateTime.getTime() / 1000) >= Math.floor(this.getStart().getTime() / 1000) && Math.floor(dateTime.getTime() / 1000) <= Math.floor(this.getEnd().getTime() / 1000)},
|
2769
|
+
isValid: function() {return this.getStart().getTime() < this.getEnd().getTime()}
|
2770
|
+
};
|
2771
|
+
|
2772
|
+
/**
|
2773
|
+
* @constructor
|
2774
|
+
* single user freebusy manager.
|
2775
|
+
*/
|
2776
|
+
var FreeBusy = function(options) {
|
2777
|
+
this.options = $.extend({}, options || {});
|
2778
|
+
};
|
2779
|
+
$.extend(FreeBusy.prototype, FreeBusyProto);
|
2780
|
+
|
2781
|
+
var FreeBusyManager = function(options) {
|
2782
|
+
this.options = $.extend({
|
2783
|
+
defaultFreeBusy: {}
|
2784
|
+
}, options || {});
|
2785
|
+
this.freeBusys = [];
|
2786
|
+
this.freeBusys.push(new FreeBusy($.extend({
|
2787
|
+
start: this.getStart(),
|
2788
|
+
end: this.getEnd()
|
2789
|
+
}, this.options.defaultFreeBusy)));
|
2790
|
+
};
|
2791
|
+
$.extend(FreeBusyManager.prototype, FreeBusyProto, {
|
2792
|
+
/**
|
2793
|
+
* return matching freeBusys.
|
2794
|
+
* if you do not pass any argument, returns all freebusys.
|
2795
|
+
* if you only pass a start date, only matchinf freebusy will be returned.
|
2796
|
+
* if you pass 2 arguments, then all freebusys available within the time period will be returned
|
2797
|
+
* @param {Date} start [optionnal] if you do not pass end date, will return the freeBusy within which this date falls.
|
2798
|
+
* @param {Date} end [optionnal] the date where to stop the search.
|
2799
|
+
* @return {Array} an array of FreeBusy matching arguments.
|
2800
|
+
*/
|
2801
|
+
getFreeBusys: function() {
|
2802
|
+
switch (arguments.length) {
|
2803
|
+
case 0:
|
2804
|
+
return this.freeBusys;
|
2805
|
+
case 1:
|
2806
|
+
var freeBusy = [];
|
2807
|
+
var start = arguments[0];
|
2808
|
+
if (!this.isWithin(start)) {
|
2809
|
+
return freeBusy;
|
2810
|
+
}
|
2811
|
+
$.each(this.freeBusys, function() {
|
2812
|
+
if (this.isWithin(start)) {
|
2813
|
+
freeBusy.push(this);
|
2814
|
+
}
|
2815
|
+
if (Math.floor(this.getEnd().getTime() / 1000) > Math.floor(start.getTime() / 1000)) {
|
2816
|
+
return false;
|
2817
|
+
}
|
2818
|
+
});
|
2819
|
+
return freeBusy;
|
2820
|
+
default:
|
2821
|
+
//we assume only 2 first args are revealants
|
2822
|
+
var freeBusy = [];
|
2823
|
+
var start = arguments[0], end = arguments[1];
|
2824
|
+
var tmpFreeBusy = new FreeBusy({start: start, end: end});
|
2825
|
+
if (end.getTime() < start.getTime() || this.getStart().getTime() > end.getTime() || this.getEnd().getTime() < start.getTime()) {
|
2826
|
+
return freeBusy;
|
2827
|
+
}
|
2828
|
+
$.each(this.freeBusys, function() {
|
2829
|
+
if (this.getStart().getTime() >= end.getTime()) {
|
2830
|
+
return false;
|
2831
|
+
}
|
2832
|
+
if (tmpFreeBusy.isWithin(this.getStart()) && tmpFreeBusy.isWithin(this.getEnd())) {
|
2833
|
+
freeBusy.push(this);
|
2834
|
+
}
|
2835
|
+
else if (this.isWithin(tmpFreeBusy.getStart()) && this.isWithin(tmpFreeBusy.getEnd())) {
|
2836
|
+
var _f = new FreeBusy(this.getOption());
|
2837
|
+
_f.setOption('end', tmpFreeBusy.getEnd());
|
2838
|
+
_f.setOption('start', tmpFreeBusy.getStart());
|
2839
|
+
freeBusy.push(_f);
|
2840
|
+
}
|
2841
|
+
else if (this.isWithin(tmpFreeBusy.getStart()) && this.getStart().getTime() < start.getTime()) {
|
2842
|
+
var _f = new FreeBusy(this.getOption());
|
2843
|
+
_f.setOption('start', tmpFreeBusy.getStart());
|
2844
|
+
freeBusy.push(_f);
|
2845
|
+
}
|
2846
|
+
else if (this.isWithin(tmpFreeBusy.getEnd()) && this.getEnd().getTime() > end.getTime()) {
|
2847
|
+
var _f = new FreeBusy(this.getOption());
|
2848
|
+
_f.setOption('end', tmpFreeBusy.getEnd());
|
2849
|
+
freeBusy.push(_f);
|
2850
|
+
}
|
2851
|
+
});
|
2852
|
+
return freeBusy;
|
2853
|
+
}
|
2854
|
+
},
|
2855
|
+
insertFreeBusy: function(freeBusy) {
|
2856
|
+
var freeBusy = new FreeBusy(freeBusy.getOption());
|
2857
|
+
//first, if inserted freebusy is bigger than manager
|
2858
|
+
if (freeBusy.getStart().getTime() < this.getStart().getTime()) {
|
2859
|
+
freeBusy.setOption('start', this.getStart());
|
2860
|
+
}
|
2861
|
+
if (freeBusy.getEnd().getTime() > this.getEnd().getTime()) {
|
2862
|
+
freeBusy.setOption('end', this.getEnd());
|
2863
|
+
}
|
2864
|
+
var start = freeBusy.getStart(), end = freeBusy.getEnd(),
|
2865
|
+
startIndex = 0, endIndex = this.freeBusys.length - 1,
|
2866
|
+
newFreeBusys = [];
|
2867
|
+
var pushNewFreeBusy = function(_f) {if (_f.isValid()) newFreeBusys.push(_f);};
|
2868
|
+
|
2869
|
+
$.each(this.freeBusys, function(index) {
|
2870
|
+
//within the loop, we have following vars:
|
2871
|
+
// curFreeBusyItem: the current iteration freeBusy, part of manager freeBusys list
|
2872
|
+
// start: the insterted freeBusy start
|
2873
|
+
// end: the inserted freebusy end
|
2874
|
+
var curFreeBusyItem = this;
|
2875
|
+
if (curFreeBusyItem.isWithin(start) && curFreeBusyItem.isWithin(end)) {
|
2876
|
+
/*
|
2877
|
+
we are in case where inserted freebusy fits in curFreeBusyItem:
|
2878
|
+
curFreeBusyItem: *-----------------------------*
|
2879
|
+
freeBusy: *-------------*
|
2880
|
+
obviously, start and end indexes are this item.
|
2881
|
+
*/
|
2882
|
+
startIndex = index;
|
2883
|
+
endIndex = index;
|
2884
|
+
if (start.getTime() == curFreeBusyItem.getStart().getTime() && end.getTime() == curFreeBusyItem.getEnd().getTime()) {
|
2885
|
+
/*
|
2886
|
+
in this case, inserted freebusy is exactly curFreeBusyItem:
|
2887
|
+
curFreeBusyItem: *-----------------------------*
|
2888
|
+
freeBusy: *-----------------------------*
|
2889
|
+
|
2890
|
+
just replace curFreeBusyItem with freeBusy.
|
2891
|
+
*/
|
2892
|
+
var _f1 = new FreeBusy(freeBusy.getOption());
|
2893
|
+
pushNewFreeBusy(_f1);
|
2894
|
+
}
|
2895
|
+
else if (start.getTime() == curFreeBusyItem.getStart().getTime()) {
|
2896
|
+
/*
|
2897
|
+
in this case inserted freebusy starts with curFreeBusyItem:
|
2898
|
+
curFreeBusyItem: *-----------------------------*
|
2899
|
+
freeBusy: *--------------*
|
2900
|
+
|
2901
|
+
just replace curFreeBusyItem with freeBusy AND the rest.
|
2902
|
+
*/
|
2903
|
+
var _f1 = new FreeBusy(freeBusy.getOption());
|
2904
|
+
var _f2 = new FreeBusy(curFreeBusyItem.getOption());
|
2905
|
+
_f2.setOption('start', end);
|
2906
|
+
pushNewFreeBusy(_f1);
|
2907
|
+
pushNewFreeBusy(_f2);
|
2908
|
+
}
|
2909
|
+
else if (end.getTime() == curFreeBusyItem.getEnd().getTime()) {
|
2910
|
+
/*
|
2911
|
+
in this case inserted freebusy ends with curFreeBusyItem:
|
2912
|
+
curFreeBusyItem: *-----------------------------*
|
2913
|
+
freeBusy: *--------------*
|
2914
|
+
|
2915
|
+
just replace curFreeBusyItem with before part AND freeBusy.
|
2916
|
+
*/
|
2917
|
+
var _f1 = new FreeBusy(curFreeBusyItem.getOption());
|
2918
|
+
_f1.setOption('end', start);
|
2919
|
+
var _f2 = new FreeBusy(freeBusy.getOption());
|
2920
|
+
pushNewFreeBusy(_f1);
|
2921
|
+
pushNewFreeBusy(_f2);
|
2922
|
+
}
|
2923
|
+
else {
|
2924
|
+
/*
|
2925
|
+
in this case inserted freebusy is within curFreeBusyItem:
|
2926
|
+
curFreeBusyItem: *-----------------------------*
|
2927
|
+
freeBusy: *--------------*
|
2928
|
+
|
2929
|
+
just replace curFreeBusyItem with before part AND freeBusy AND the rest.
|
2930
|
+
*/
|
2931
|
+
var _f1 = new FreeBusy(curFreeBusyItem.getOption());
|
2932
|
+
var _f2 = new FreeBusy(freeBusy.getOption());
|
2933
|
+
var _f3 = new FreeBusy(curFreeBusyItem.getOption());
|
2934
|
+
_f1.setOption('end', start);
|
2935
|
+
_f3.setOption('start', end);
|
2936
|
+
pushNewFreeBusy(_f1);
|
2937
|
+
pushNewFreeBusy(_f2);
|
2938
|
+
pushNewFreeBusy(_f3);
|
2939
|
+
}
|
2940
|
+
/*
|
2941
|
+
as work is done, no need to go further.
|
2942
|
+
return false
|
2943
|
+
*/
|
2944
|
+
return false;
|
2945
|
+
}
|
2946
|
+
else if (curFreeBusyItem.isWithin(start) && curFreeBusyItem.getEnd().getTime() != start.getTime()) {
|
2947
|
+
/*
|
2948
|
+
in this case, inserted freebusy starts within curFreeBusyItem:
|
2949
|
+
curFreeBusyItem: *----------*
|
2950
|
+
freeBusy: *-------------------*
|
2951
|
+
|
2952
|
+
set start index AND insert before part, we'll insert freebusy later
|
2953
|
+
*/
|
2954
|
+
if (curFreeBusyItem.getStart().getTime() != start.getTime()) {
|
2955
|
+
var _f1 = new FreeBusy(curFreeBusyItem.getOption());
|
2956
|
+
_f1.setOption('end', start);
|
2957
|
+
pushNewFreeBusy(_f1);
|
2958
|
+
}
|
2959
|
+
startIndex = index;
|
2960
|
+
}
|
2961
|
+
else if (curFreeBusyItem.isWithin(end) && curFreeBusyItem.getStart().getTime() != end.getTime()) {
|
2962
|
+
/*
|
2963
|
+
in this case, inserted freebusy starts within curFreeBusyItem:
|
2964
|
+
curFreeBusyItem: *----------*
|
2965
|
+
freeBusy: *-------------------*
|
2966
|
+
|
2967
|
+
set end index AND insert freebusy AND insert after part if needed
|
2968
|
+
*/
|
2969
|
+
pushNewFreeBusy(new FreeBusy(freeBusy.getOption()));
|
2970
|
+
if (end.getTime() < curFreeBusyItem.getEnd().getTime()) {
|
2971
|
+
var _f1 = new FreeBusy(curFreeBusyItem.getOption());
|
2972
|
+
_f1.setOption('start', end);
|
2973
|
+
pushNewFreeBusy(_f1);
|
2974
|
+
}
|
2975
|
+
endIndex = index;
|
2976
|
+
return false;
|
2977
|
+
}
|
2978
|
+
});
|
2979
|
+
//now compute arguments
|
2980
|
+
var tmpFB = this.freeBusys;
|
2981
|
+
this.freeBusys = [];
|
2982
|
+
|
2983
|
+
if (startIndex) {
|
2984
|
+
this.freeBusys = this.freeBusys.concat(tmpFB.slice(0, startIndex));
|
2985
|
+
}
|
2986
|
+
this.freeBusys = this.freeBusys.concat(newFreeBusys);
|
2987
|
+
if (endIndex < tmpFB.length) {
|
2988
|
+
this.freeBusys = this.freeBusys.concat(tmpFB.slice(endIndex + 1));
|
2989
|
+
}
|
2990
|
+
/* if(start.getDate() == 1){
|
2991
|
+
console.info('insert from '+freeBusy.getStart() +' to '+freeBusy.getEnd());
|
2992
|
+
console.log('index from '+ startIndex + ' to ' + endIndex);
|
2993
|
+
var str = [];
|
2994
|
+
$.each(tmpFB, function(i){str.push(i + ": " + this.getStart().getHours() + ' > ' + this.getEnd().getHours() + ' ' + (this.getOption('free') ? 'free' : 'busy'))});
|
2995
|
+
console.log(str.join('\n'));
|
2996
|
+
|
2997
|
+
console.log('insert');
|
2998
|
+
var str = [];
|
2999
|
+
$.each(newFreeBusys, function(i){str.push(this.getStart().getHours() + ' > ' + this.getEnd().getHours())});
|
3000
|
+
console.log(str.join(', '));
|
3001
|
+
|
3002
|
+
console.log('results');
|
3003
|
+
var str = [];
|
3004
|
+
$.each(this.freeBusys, function(i){str.push(i + ": " + this.getStart().getHours() + ' > ' + this.getEnd().getHours() + ' ' + (this.getOption('free') ? 'free' :'busy'))});
|
3005
|
+
console.log(str.join('\n'));
|
3006
|
+
}*/
|
3007
|
+
return this;
|
3008
|
+
}
|
3009
|
+
});
|
3010
|
+
|
3011
|
+
})(jQuery);
|