| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243 |
- /**
- * Bootstrap based calendar full view.
- *
- * https://github.com/Serhioromano/bootstrap-calendar
- *
- * User: Sergey Romanov <serg4172@mail.ru>
- */
- "use strict";
- Date.prototype.getWeek = function() {
- var onejan = new Date(this.getFullYear(), 0, 1);
- return Math.ceil((((this.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7);
- };
- Date.prototype.getMonthFormatted = function() {
- var month = this.getMonth() + 1;
- return month < 10 ? '0' + month : month;
- };
- Date.prototype.getDateFormatted = function() {
- var date = this.getDate();
- return date < 10 ? '0' + date : date;
- };
- if(!String.prototype.format) {
- String.prototype.format = function() {
- var args = arguments;
- return this.replace(/{(\d+)}/g, function(match, number) {
- return typeof args[number] != 'undefined' ? args[number] : match;
- });
- };
- }
- if(!String.prototype.formatNum) {
- String.prototype.formatNum = function(decimal) {
- var r = "" + this;
- while(r.length < decimal)
- r = "0" + r;
- return r;
- };
- }
- (function($) {
- var defaults = {
- // Width of the calendar
- width: '100%',
- // Initial view (can be 'month', 'week', 'day')
- view: 'month',
- // Initial date. No matter month, week or day this will be a starting point. Can be 'now' or a date in format 'yyyy-mm-dd'
- day: 'now',
- // Day Start time and end time with time intervals. Time split 10, 15 or 30.
- time_start: '06:00',
- time_end: '22:00',
- time_split: '30',
- // Source of events data. It can be one of the following:
- // - URL to return JSON list of events in special format.
- // {success:1, result: [....]} or for error {success:0, error:'Something terrible happened'}
- // events: [...] as described in events property description
- // The start and end variables will be sent to this url
- // - A function that received the start and end date, and that
- // returns an array of events (as described in events property description)
- // - An array containing the events
- events_source: '',
- // Set format12 to true if you want to use 12 Hour format instead of 24 Hour
- format12: false,
- am_suffix: "AM",
- pm_suffix: "PM",
- // Path to templates should end with slash /. It can be as relative
- // /component/bootstrap-calendar/tmpls/
- // or absolute
- // http://localhost/component/bootstrap-calendar/tmpls/
- tmpl_path: 'tmpls/',
- tmpl_cache: true,
- classes: {
- months: {
- inmonth: 'cal-day-inmonth',
- outmonth: 'cal-day-outmonth',
- saturday: 'cal-day-weekend',
- sunday: 'cal-day-weekend',
- holidays: 'cal-day-holiday',
- today: 'cal-day-today'
- },
- week: {
- workday: 'cal-day-workday',
- saturday: 'cal-day-weekend',
- sunday: 'cal-day-weekend',
- holidays: 'cal-day-holiday',
- today: 'cal-day-today'
- }
- },
- // ID of the element of modal window. If set, events URLs will be opened in modal windows.
- modal: null,
- // modal handling setting, one of "iframe", "ajax" or "template"
- modal_type: "iframe",
- // function to set modal title, will be passed the event as a parameter
- modal_title: null,
- views: {
- year: {
- slide_events: 1,
- enable: 1
- },
- month: {
- slide_events: 1,
- enable: 1
- },
- week: {
- enable: 1
- },
- day: {
- enable: 1
- }
- },
- merge_holidays: false,
- display_week_numbers: true,
- weekbox: true,
- // ------------------------------------------------------------
- // CALLBACKS. Events triggered by calendar class. You can use
- // those to affect you UI
- // ------------------------------------------------------------
- onAfterEventsLoad: function(events) {
- // Inside this function 'this' is the calendar instance
- },
- onBeforeEventsLoad: function(next) {
- // Inside this function 'this' is the calendar instance
- next();
- },
- onAfterViewLoad: function(view) {
- // Inside this function 'this' is the calendar instance
- },
- onAfterModalShown: function(events) {
- // Inside this function 'this' is the calendar instance
- },
- onAfterModalHidden: function(events) {
- // Inside this function 'this' is the calendar instance
- },
- // -------------------------------------------------------------
- // INTERNAL USE ONLY. DO NOT ASSIGN IT WILL BE OVERRIDDEN ANYWAY
- // -------------------------------------------------------------
- events: [],
- templates: {
- year: '',
- month: '',
- week: '',
- day: ''
- },
- stop_cycling: false
- };
- var defaults_extended = {
- first_day: 2,
- holidays: {
- // January 1
- '01-01': "New Year's Day",
- // Third (+3*) Monday (1) in January (01)
- '01+3*1': "Birthday of Dr. Martin Luther King, Jr.",
- // Third (+3*) Monday (1) in February (02)
- '02+3*1': "Washington's Birthday",
- // Last (-1*) Monday (1) in May (05)
- '05-1*1': "Memorial Day",
- // July 4
- '04-07': "Independence Day",
- // First (+1*) Monday (1) in September (09)
- '09+1*1': "Labor Day",
- // Second (+2*) Monday (1) in October (10)
- '10+2*1': "Columbus Day",
- // November 11
- '11-11': "Veterans Day",
- // Fourth (+4*) Thursday (4) in November (11)
- '11+4*4': "Thanksgiving Day",
- // December 25
- '25-12': "Christmas"
- }
- };
- var strings = {
- error_noview: 'Calendar: View {0} not found',
- error_dateformat: 'Calendar: Wrong date format {0}. Should be either "now" or "yyyy-mm-dd"',
- error_loadurl: 'Calendar: Event URL is not set',
- error_where: 'Calendar: Wrong navigation direction {0}. Can be only "next" or "prev" or "today"',
- error_timedevide: 'Calendar: Time split parameter should divide 60 without decimals. Something like 10, 15, 30',
- no_events_in_day: 'No events in this day.',
- title_year: '{0}',
- title_month: '{0} {1}',
- title_week: 'week {0} of {1}',
- title_day: '{0} {1} {2}, {3}',
- week: 'Week {0}',
- all_day: 'All day',
- time: 'Time',
- events: 'Events',
- before_time: 'Ends before timeline',
- after_time: 'Starts after timeline',
- m0: 'January',
- m1: 'February',
- m2: 'March',
- m3: 'April',
- m4: 'May',
- m5: 'June',
- m6: 'July',
- m7: 'August',
- m8: 'September',
- m9: 'October',
- m10: 'November',
- m11: 'December',
- ms0: 'Jan',
- ms1: 'Feb',
- ms2: 'Mar',
- ms3: 'Apr',
- ms4: 'May',
- ms5: 'Jun',
- ms6: 'Jul',
- ms7: 'Aug',
- ms8: 'Sep',
- ms9: 'Oct',
- ms10: 'Nov',
- ms11: 'Dec',
- d0: 'Sunday',
- d1: 'Monday',
- d2: 'Tuesday',
- d3: 'Wednesday',
- d4: 'Thursday',
- d5: 'Friday',
- d6: 'Saturday'
- };
- var browser_timezone = '';
- try {
- if($.type(window.jstz) == 'object' && $.type(jstz.determine) == 'function') {
- browser_timezone = jstz.determine().name();
- if($.type(browser_timezone) !== 'string') {
- browser_timezone = '';
- }
- }
- }
- catch(e) {
- }
- function buildEventsUrl(events_url, data) {
- var separator, key, url;
- url = events_url;
- separator = (events_url.indexOf('?') < 0) ? '?' : '&';
- for(key in data) {
- url += separator + key + '=' + encodeURIComponent(data[key]);
- separator = '&';
- }
- return url;
- }
- function getExtentedOption(cal, option_name) {
- var fromOptions = (cal.options[option_name] != null) ? cal.options[option_name] : null;
- var fromLanguage = (cal.locale[option_name] != null) ? cal.locale[option_name] : null;
- if((option_name == 'holidays') && cal.options.merge_holidays) {
- var holidays = {};
- $.extend(true, holidays, fromLanguage ? fromLanguage : defaults_extended.holidays);
- if(fromOptions) {
- $.extend(true, holidays, fromOptions);
- }
- return holidays;
- }
- else {
- if(fromOptions != null) {
- return fromOptions;
- }
- if(fromLanguage != null) {
- return fromLanguage;
- }
- return defaults_extended[option_name];
- }
- }
- function getHolidays(cal, year) {
- var hash = [];
- var holidays_def = getExtentedOption(cal, 'holidays');
- for(var k in holidays_def) {
- hash.push(k + ':' + holidays_def[k]);
- }
- hash.push(year);
- hash = hash.join('|');
- if(hash in getHolidays.cache) {
- return getHolidays.cache[hash];
- }
- var holidays = [];
- $.each(holidays_def, function(key, name) {
- var firstDay = null, lastDay = null, failed = false;
- $.each(key.split('>'), function(i, chunk) {
- var m, date = null;
- if(m = /^(\d\d)-(\d\d)$/.exec(chunk)) {
- date = new Date(year, parseInt(m[2], 10) - 1, parseInt(m[1], 10));
- }
- else if(m = /^(\d\d)-(\d\d)-(\d\d\d\d)$/.exec(chunk)) {
- if(parseInt(m[3], 10) == year) {
- date = new Date(year, parseInt(m[2], 10) - 1, parseInt(m[1], 10));
- }
- }
- else if(m = /^easter(([+\-])(\d+))?$/.exec(chunk)) {
- date = getEasterDate(year, m[1] ? parseInt(m[1], 10) : 0);
- }
- else if(m = /^(\d\d)([+\-])([1-5])\*([0-6])$/.exec(chunk)) {
- var month = parseInt(m[1], 10) - 1;
- var direction = m[2];
- var offset = parseInt(m[3]);
- var weekday = parseInt(m[4]);
- switch(direction) {
- case '+':
- var d = new Date(year, month, 1 - 7);
- while(d.getDay() != weekday) {
- d = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1);
- }
- date = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 7 * offset);
- break;
- case '-':
- var d = new Date(year, month + 1, 0 + 7);
- while(d.getDay() != weekday) {
- d = new Date(d.getFullYear(), d.getMonth(), d.getDate() - 1);
- }
- date = new Date(d.getFullYear(), d.getMonth(), d.getDate() - 7 * offset);
- break;
- }
- }
- if(!date) {
- warn('Unknown holiday: ' + key);
- failed = true;
- return false;
- }
- switch(i) {
- case 0:
- firstDay = date;
- break;
- case 1:
- if(date.getTime() <= firstDay.getTime()) {
- warn('Unknown holiday: ' + key);
- failed = true;
- return false;
- }
- lastDay = date;
- break;
- default:
- warn('Unknown holiday: ' + key);
- failed = true;
- return false;
- }
- });
- if(!failed) {
- var days = [];
- if(lastDay) {
- for(var date = new Date(firstDay.getTime()); date.getTime() <= lastDay.getTime(); date.setDate(date.getDate() + 1)) {
- days.push(new Date(date.getTime()));
- }
- }
- else {
- days.push(firstDay);
- }
- holidays.push({name: name, days: days});
- }
- });
- getHolidays.cache[hash] = holidays;
- return getHolidays.cache[hash];
- }
- getHolidays.cache = {};
- function warn(message) {
- if($.type(window.console) == 'object' && $.type(window.console.warn) == 'function') {
- window.console.warn('[Bootstrap-Calendar] ' + message);
- }
- }
- function Calendar(params, context) {
- this.options = $.extend(true, {position: {start: new Date(), end: new Date()}}, defaults, params);
- this.setLanguage(this.options.language);
- this.context = context;
- context.css('width', this.options.width).addClass('cal-context');
- this.view();
- return this;
- }
- Calendar.prototype.setOptions = function(object) {
- $.extend(this.options, object);
- if('language' in object) {
- this.setLanguage(object.language);
- }
- if('modal' in object) {
- this._update_modal();
- }
- }
- Calendar.prototype.setLanguage = function(lang) {
- if(window.calendar_languages && (lang in window.calendar_languages)) {
- this.locale = $.extend(true, {}, strings, calendar_languages[lang]);
- this.options.language = lang;
- } else {
- this.locale = strings;
- delete this.options.language;
- }
- }
- Calendar.prototype._render = function() {
- this.context.html('');
- this._loadTemplate(this.options.view);
- this.stop_cycling = false;
- var data = {};
- data.cal = this;
- data.day = 1;
- // Getting list of days in a week in correct order. Works for month and week views
- if(getExtentedOption(this, 'first_day') == 1) {
- data.days_name = [this.locale.d1, this.locale.d2, this.locale.d3, this.locale.d4, this.locale.d5, this.locale.d6, this.locale.d0]
- } else {
- data.days_name = [this.locale.d0, this.locale.d1, this.locale.d2, this.locale.d3, this.locale.d4, this.locale.d5, this.locale.d6]
- }
- // Get all events between start and end
- var start = parseInt(this.options.position.start.getTime());
- var end = parseInt(this.options.position.end.getTime());
- data.events = this.getEventsBetween(start, end);
- switch(this.options.view) {
- case 'month':
- break;
- case 'week':
- this._calculate_hour_minutes(data);
- break;
- case 'day':
- this._calculate_hour_minutes(data);
- break;
- }
- data.start = new Date(this.options.position.start.getTime());
- data.lang = this.locale;
- this.context.append(this.options.templates[this.options.view](data));
- this._update();
- };
- Calendar.prototype._format_hour = function(str_hour) {
- var hour_split = str_hour.split(":");
- var hour = parseInt(hour_split[0]);
- var minutes = parseInt(hour_split[1]);
- var suffix = '';
- if(this.options.format12) {
- if(hour < 12) {
- suffix = this.options.am_suffix;
- }
- else {
- suffix = this.options.pm_suffix;
- }
- hour = hour % 12;
- if(hour == 0) {
- hour = 12;
- }
- }
- return hour.toString().formatNum(2) + ':' + minutes.toString().formatNum(2) + suffix;
- };
- Calendar.prototype._format_time = function(datetime) {
- return this._format_hour(datetime.getHours() + ':' + datetime.getMinutes());
- };
- Calendar.prototype._calculate_hour_minutes = function(data) {
- var $self = this;
- var time_split = parseInt(this.options.time_split);
- var time_split_count = 60 / time_split;
- var time_split_hour = Math.min(time_split_count, 1);
- if(((time_split_count >= 1) && (time_split_count % 1 != 0)) || ((time_split_count < 1) && (1440 / time_split % 1 != 0))) {
- $.error(this.locale.error_timedevide);
- }
- var time_start = this.options.time_start.split(":");
- var time_end = this.options.time_end.split(":");
- data.hours = (parseInt(time_end[0]) - parseInt(time_start[0])) * time_split_hour;
- var lines = data.hours * time_split_count - parseInt(time_start[1]) / time_split;
- var ms_per_line = (60000 * time_split);
- var start = new Date(this.options.position.start.getTime());
- start.setHours(time_start[0]);
- start.setMinutes(time_start[1]);
- var end = new Date(this.options.position.end.getTime());
- end.setHours(time_end[0]);
- end.setMinutes(time_end[1]);
- data.all_day = [];
- data.by_hour = [];
- data.after_time = [];
- data.before_time = [];
- $.each(data.events, function(k, e) {
- var s = new Date(parseInt(e.start));
- var f = new Date(parseInt(e.end));
- e.start_hour = $self._format_time(s);
- e.end_hour = $self._format_time(f);
- if(e.start < start.getTime()) {
- warn(1);
- e.start_hour = s.getDate() + ' ' + $self.locale['ms' + s.getMonth()] + ' ' + e.start_hour;
- }
- if(e.end > end.getTime()) {
- warn(1);
- e.end_hour = f.getDate() + ' ' + $self.locale['ms' + f.getMonth()] + ' ' + e.end_hour;
- }
- if(e.start < start.getTime() && e.end > end.getTime()) {
- data.all_day.push(e);
- return;
- }
- if(e.end < start.getTime()) {
- data.before_time.push(e);
- return;
- }
- if(e.start > end.getTime()) {
- data.after_time.push(e);
- return;
- }
- var event_start = start.getTime() - e.start;
- if(event_start >= 0) {
- e.top = 0;
- } else {
- e.top = Math.abs(event_start) / ms_per_line;
- }
- var lines_left = Math.abs(lines - e.top);
- var lines_in_event = (e.end - e.start) / ms_per_line;
- if(event_start >= 0) {
- lines_in_event = (e.end - start.getTime()) / ms_per_line;
- }
- e.lines = lines_in_event;
- if(lines_in_event > lines_left) {
- e.lines = lines_left;
- }
- data.by_hour.push(e);
- });
- //var d = new Date('2013-03-14 13:20:00');
- //warn(d.getTime());
- };
- Calendar.prototype._hour_min = function(hour) {
- var time_start = this.options.time_start.split(":");
- var time_split = parseInt(this.options.time_split);
- var in_hour = 60 / time_split;
- return (hour == 0) ? (in_hour - (parseInt(time_start[1]) / time_split)) : in_hour;
- };
- Calendar.prototype._hour = function(hour, part) {
- var time_start = this.options.time_start.split(":");
- var time_split = parseInt(this.options.time_split);
- var h = "" + (parseInt(time_start[0]) + hour * Math.max(time_split / 60, 1));
- var m = "" + time_split * part;
- return this._format_hour(h.formatNum(2) + ":" + m.formatNum(2));
- };
- Calendar.prototype._week = function(event) {
- this._loadTemplate('week-days');
- var t = {};
- var start = parseInt(this.options.position.start.getTime());
- var end = parseInt(this.options.position.end.getTime());
- var events = [];
- var self = this;
- var first_day = getExtentedOption(this, 'first_day');
- $.each(this.getEventsBetween(start, end), function(k, event) {
- event.start_day = new Date(parseInt(event.start)).getDay();
- if(first_day == 1) {
- event.start_day = (event.start_day + 6) % 7;
- }
- if((event.end - event.start) <= 86400000) {
- event.days = 1;
- } else {
- event.days = ((event.end - event.start) / 86400000);
- }
- if(event.start < start) {
- event.days = event.days - ((start - event.start) / 86400000);
- event.start_day = 0;
- }
- event.days = Math.ceil(event.days);
- if(event.start_day + event.days > 7) {
- event.days = 7 - (event.start_day);
- }
- events.push(event);
- });
- t.events = events;
- t.cal = this;
- return self.options.templates['week-days'](t);
- }
- Calendar.prototype._month = function(month) {
- this._loadTemplate('year-month');
- var t = {cal: this};
- var newmonth = month + 1;
- t.data_day = this.options.position.start.getFullYear() + '-' + (newmonth < 10 ? '0' + newmonth : newmonth) + '-' + '01';
- t.month_name = this.locale['m' + month];
- var curdate = new Date(this.options.position.start.getFullYear(), month, 1, 0, 0, 0);
- t.start = parseInt(curdate.getTime());
- t.end = parseInt(new Date(this.options.position.start.getFullYear(), month + 1, 1, 0, 0, 0).getTime());
- t.events = this.getEventsBetween(t.start, t.end);
- return this.options.templates['year-month'](t);
- }
- Calendar.prototype._day = function(week, day) {
- this._loadTemplate('month-day');
- var t = {tooltip: '', cal: this};
- var cls = this.options.classes.months.outmonth;
- var firstday = this.options.position.start.getDay();
- if(getExtentedOption(this, 'first_day') == 2) {
- firstday++;
- } else {
- firstday = (firstday == 0 ? 7 : firstday);
- }
- day = (day - firstday) + 1;
- var curdate = new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), day, 0, 0, 0);
- // if day of the current month
- if(day > 0) {
- cls = this.options.classes.months.inmonth;
- }
- // stop cycling table rows;
- var daysinmonth = (new Date(this.options.position.end.getTime() - 1)).getDate();
- if((day + 1) > daysinmonth) {
- this.stop_cycling = true;
- }
- // if day of the next month
- if(day > daysinmonth) {
- day = day - daysinmonth;
- cls = this.options.classes.months.outmonth;
- }
- cls = $.trim(cls + " " + this._getDayClass("months", curdate));
- if(day <= 0) {
- var daysinprevmonth = (new Date(this.options.position.start.getFullYear(), this.options.position.start.getMonth(), 0)).getDate();
- day = daysinprevmonth - Math.abs(day);
- cls += ' cal-month-first-row';
- }
- var holiday = this._getHoliday(curdate);
- if(holiday !== false) {
- t.tooltip = holiday;
- }
- t.data_day = curdate.getFullYear() + '-' + curdate.getMonthFormatted() + '-' + (day < 10 ? '0' + day : day);
- t.cls = cls;
- t.day = day;
- t.start = parseInt(curdate.getTime());
- t.end = parseInt(t.start + 86400000);
- t.events = this.getEventsBetween(t.start, t.end);
- return this.options.templates['month-day'](t);
- }
- Calendar.prototype._getHoliday = function(date) {
- var result = false;
- $.each(getHolidays(this, date.getFullYear()), function() {
- var found = false;
- $.each(this.days, function() {
- if(this.toDateString() == date.toDateString()) {
- found = true;
- return false;
- }
- });
- if(found) {
- result = this.name;
- return false;
- }
- });
- return result;
- };
- Calendar.prototype._getHolidayName = function(date) {
- var holiday = this._getHoliday(date);
- return (holiday === false) ? "" : holiday;
- };
- Calendar.prototype._getDayClass = function(class_group, date) {
- var self = this;
- var addClass = function(which, to) {
- var cls;
- cls = (self.options.classes && (class_group in self.options.classes) && (which in self.options.classes[class_group])) ? self.options.classes[class_group][which] : "";
- if((typeof(cls) == "string") && cls.length) {
- to.push(cls);
- }
- };
- var classes = [];
- if(date.toDateString() == (new Date()).toDateString()) {
- addClass("today", classes);
- }
- var holiday = this._getHoliday(date);
- if(holiday !== false) {
- addClass("holidays", classes);
- }
- switch(date.getDay()) {
- case 0:
- addClass("sunday", classes);
- break;
- case 6:
- addClass("saturday", classes);
- break;
- }
- addClass(date.toDateString(), classes);
- return classes.join(" ");
- };
- Calendar.prototype.view = function(view) {
- if(view) {
- if(!this.options.views[view].enable) {
- return;
- }
- this.options.view = view;
- }
- this._init_position();
- this._loadEvents();
- this._render();
- this.options.onAfterViewLoad.call(this, this.options.view);
- };
- Calendar.prototype.navigate = function(where, next) {
- var to = $.extend({}, this.options.position);
- if(where == 'next') {
- switch(this.options.view) {
- case 'year':
- to.start.setFullYear(this.options.position.start.getFullYear() + 1);
- break;
- case 'month':
- to.start.setMonth(this.options.position.start.getMonth() + 1);
- break;
- case 'week':
- to.start.setDate(this.options.position.start.getDate() + 7);
- break;
- case 'day':
- to.start.setDate(this.options.position.start.getDate() + 1);
- break;
- }
- } else if(where == 'prev') {
- switch(this.options.view) {
- case 'year':
- to.start.setFullYear(this.options.position.start.getFullYear() - 1);
- break;
- case 'month':
- to.start.setMonth(this.options.position.start.getMonth() - 1);
- break;
- case 'week':
- to.start.setDate(this.options.position.start.getDate() - 7);
- break;
- case 'day':
- to.start.setDate(this.options.position.start.getDate() - 1);
- break;
- }
- } else if(where == 'today') {
- to.start.setTime(new Date().getTime());
- }
- else {
- $.error(this.locale.error_where.format(where))
- }
- this.options.day = to.start.getFullYear() + '-' + to.start.getMonthFormatted() + '-' + to.start.getDateFormatted();
- this.view();
- if(_.isFunction(next)) {
- next();
- }
- };
- Calendar.prototype._init_position = function() {
- var year, month, day;
- if(this.options.day == 'now') {
- var date = new Date();
- year = date.getFullYear();
- month = date.getMonth();
- day = date.getDate();
- } else if(this.options.day.match(/^\d{4}-\d{2}-\d{2}$/g)) {
- var list = this.options.day.split('-');
- year = parseInt(list[0], 10);
- month = parseInt(list[1], 10) - 1;
- day = parseInt(list[2], 10);
- }
- else {
- $.error(this.locale.error_dateformat.format(this.options.day));
- }
- switch(this.options.view) {
- case 'year':
- this.options.position.start.setTime(new Date(year, 0, 1).getTime());
- this.options.position.end.setTime(new Date(year + 1, 0, 1).getTime());
- break;
- case 'month':
- this.options.position.start.setTime(new Date(year, month, 1).getTime());
- this.options.position.end.setTime(new Date(year, month + 1, 1).getTime());
- break;
- case 'day':
- this.options.position.start.setTime(new Date(year, month, day).getTime());
- this.options.position.end.setTime(new Date(year, month, day + 1).getTime());
- break;
- case 'week':
- var curr = new Date(year, month, day);
- var first;
- if(getExtentedOption(this, 'first_day') == 1) {
- first = curr.getDate() - ((curr.getDay() + 6) % 7);
- }
- else {
- first = curr.getDate() - curr.getDay();
- }
- this.options.position.start.setTime(new Date(year, month, first).getTime());
- this.options.position.end.setTime(new Date(year, month, first + 7).getTime());
- break;
- default:
- $.error(this.locale.error_noview.format(this.options.view))
- }
- return this;
- };
- Calendar.prototype.getTitle = function() {
- var p = this.options.position.start;
- switch(this.options.view) {
- case 'year':
- return this.locale.title_year.format(p.getFullYear());
- break;
- case 'month':
- return this.locale.title_month.format(this.locale['m' + p.getMonth()], p.getFullYear());
- break;
- case 'week':
- return this.locale.title_week.format(p.getWeek(), p.getFullYear());
- break;
- case 'day':
- return this.locale.title_day.format(this.locale['d' + p.getDay()], p.getDate(), this.locale['m' + p.getMonth()], p.getFullYear());
- break;
- }
- return;
- };
- Calendar.prototype.isToday = function() {
- var now = new Date().getTime();
- return ((now > this.options.position.start) && (now < this.options.position.end));
- }
- Calendar.prototype.getStartDate = function() {
- return this.options.position.start;
- }
- Calendar.prototype.getEndDate = function() {
- return this.options.position.end;
- }
- Calendar.prototype._loadEvents = function() {
- var self = this;
- var source = null;
- if('events_source' in this.options && this.options.events_source !== '') {
- source = this.options.events_source;
- }
- else if('events_url' in this.options) {
- source = this.options.events_url;
- warn('The events_url option is DEPRECATED and it will be REMOVED in near future. Please use events_source instead.');
- }
- var loader;
- switch($.type(source)) {
- case 'function':
- loader = function() {
- return source(self.options.position.start, self.options.position.end, browser_timezone);
- };
- break;
- case 'array':
- loader = function() {
- return [].concat(source);
- };
- break;
- case 'string':
- if(source.length) {
- loader = function() {
- var events = [];
- var d = new Date();
- var utc_offset = d.getTimezoneOffset();
- var params = {from: self.options.position.start.getTime(), to: self.options.position.end.getTime(), utc_offset: utc_offset};
- if(browser_timezone.length) {
- params.browser_timezone = browser_timezone;
- }
- $.ajax({
- url: buildEventsUrl(source, params),
- dataType: 'json',
- type: 'GET',
- async: false
- }).done(function(json) {
- if(!json.success) {
- $.error(json.error);
- }
- if(json.result) {
- events = json.result;
- }
- });
- return events;
- };
- }
- break;
- }
- if(!loader) {
- $.error(this.locale.error_loadurl);
- }
- this.options.onBeforeEventsLoad.call(this, function() {
- self.options.events = loader();
- self.options.events.sort(function(a, b) {
- var delta;
- delta = a.start - b.start;
- if(delta == 0) {
- delta = a.end - b.end;
- }
- return delta;
- });
- self.options.onAfterEventsLoad.call(self, self.options.events);
- });
- };
- Calendar.prototype._templatePath = function(name) {
- if(typeof this.options.tmpl_path == 'function') {
- return this.options.tmpl_path(name)
- }
- else {
- return this.options.tmpl_path + name + '.html';
- }
- };
- Calendar.prototype._loadTemplate = function(name) {
- if(this.options.templates[name]) {
- return;
- }
- var self = this;
- $.ajax({
- url: self._templatePath(name),
- dataType: 'html',
- type: 'GET',
- async: false,
- cache: this.options.tmpl_cache
- }).done(function(html) {
- self.options.templates[name] = _.template(html);
- });
- };
- Calendar.prototype._update = function() {
- var self = this;
- $('*[data-toggle="tooltip"]').tooltip({container: 'body'});
- $('*[data-cal-date]').click(function() {
- var view = $(this).data('cal-view');
- self.options.day = $(this).data('cal-date');
- self.view(view);
- });
- $('.cal-cell').dblclick(function() {
- var view = $('[data-cal-date]', this).data('cal-view');
- self.options.day = $('[data-cal-date]', this).data('cal-date');
- self.view(view);
- });
- this['_update_' + this.options.view]();
- this._update_modal();
- };
- Calendar.prototype._update_modal = function() {
- var self = this;
- $('a[data-event-id]', this.context).unbind('click');
- if(!self.options.modal) {
- return;
- }
- var modal = $(self.options.modal);
- if(!modal.length) {
- return;
- }
- var ifrm = null;
- if(self.options.modal_type == "iframe") {
- ifrm = $(document.createElement("iframe"))
- .attr({
- width: "100%",
- frameborder: "0"
- });
- }
- $('a[data-event-id]', this.context).on('click', function(event) {
- event.preventDefault();
- event.stopPropagation();
- var url = $(this).attr('href');
- var id = $(this).data("event-id");
- var event = _.find(self.options.events, function(event) {
- return event.id == id
- });
- if(self.options.modal_type == "iframe") {
- ifrm.attr('src', url);
- $('.modal-body', modal).html(ifrm);
- }
- if(!modal.data('handled.bootstrap-calendar') || (modal.data('handled.bootstrap-calendar') && modal.data('handled.event-id') != event.id)) {
- modal.off('show.bs.modal')
- .off('shown.bs.modal')
- .off('hidden.bs.modal')
- .on('show.bs.modal', function() {
- var modal_body = $(this).find('.modal-body');
- switch(self.options.modal_type) {
- case "iframe" :
- var height = modal_body.height() - parseInt(modal_body.css('padding-top'), 10) - parseInt(modal_body.css('padding-bottom'), 10);
- $(this).find('iframe').height(Math.max(height, 50));
- break;
- case "ajax":
- $.ajax({
- url: url, dataType: "html", async: false, success: function(data) {
- modal_body.html(data);
- }
- });
- break;
- case "template":
- self._loadTemplate("modal");
- // also serve calendar instance to underscore template to be able to access current language strings
- modal_body.html(self.options.templates["modal"]({"event": event, "calendar": self}))
- break;
- }
- // set the title of the bootstrap modal
- if(_.isFunction(self.options.modal_title)) {
- modal.find(".modal-title").html(self.options.modal_title(event));
- }
- })
- .on('shown.bs.modal', function() {
- self.options.onAfterModalShown.call(self, self.options.events);
- })
- .on('hidden.bs.modal', function() {
- self.options.onAfterModalHidden.call(self, self.options.events);
- })
- .data('handled.bootstrap-calendar', true).data('handled.event-id', event.id);
- }
- modal.modal('show');
- });
- };
- Calendar.prototype._update_day = function() {
- $('#cal-day-panel').height($('#cal-day-panel-hour').height());
- };
- Calendar.prototype._update_week = function() {
- };
- Calendar.prototype._update_year = function() {
- this._update_month_year();
- };
- Calendar.prototype._update_month = function() {
- this._update_month_year();
- var self = this;
- if(this.options.weekbox == true) {
- var week = $(document.createElement('div')).attr('id', 'cal-week-box');
- var start = this.options.position.start.getFullYear() + '-' + this.options.position.start.getMonthFormatted() + '-';
- self.context.find('.cal-month-box .cal-row-fluid')
- .on('mouseenter', function() {
- var p = new Date(self.options.position.start);
- var child = $('.cal-cell1:first-child .cal-month-day', this);
- var day = (child.hasClass('cal-month-first-row') ? 1 : $('[data-cal-date]', child).text());
- p.setDate(parseInt(day));
- day = (day < 10 ? '0' + day : day);
- week.html(self.locale.week.format(self.options.display_week_numbers == true ? p.getWeek() : ''));
- week.attr('data-cal-week', start + day).show().appendTo(child);
- })
- .on('mouseleave', function() {
- week.hide();
- });
- week.click(function() {
- self.options.day = $(this).data('cal-week');
- self.view('week');
- });
- }
- $('a.event').mouseenter(function() {
- $('a[data-event-id="' + $(this).data('event-id') + '"]').closest('.cal-cell1').addClass('day-highlight dh-' + $(this).data('event-class'));
- });
- $('a.event').mouseleave(function() {
- $('div.cal-cell1').removeClass('day-highlight dh-' + $(this).data('event-class'));
- });
- };
- Calendar.prototype._update_month_year = function() {
- if(!this.options.views[this.options.view].slide_events) {
- return;
- }
- var self = this;
- var activecell = 0;
- var downbox = $(document.createElement('div')).attr('id', 'cal-day-tick').html('<i class="icon-chevron-down glyphicon glyphicon-chevron-down"></i>');
- $('.cal-month-day, .cal-year-box .span3')
- .on('mouseenter', function() {
- if($('.events-list', this).length == 0) {
- return;
- }
- if($(this).children('[data-cal-date]').text() == self.activecell) {
- return;
- }
- downbox.show().appendTo(this);
- })
- .on('mouseleave', function() {
- downbox.hide();
- })
- .on('click', function(event) {
- if($('.events-list', this).length == 0) {
- return;
- }
- if($(this).children('[data-cal-date]').text() == self.activecell) {
- return;
- }
- showEventsList(event, downbox, slider, self);
- })
- ;
- var slider = $(document.createElement('div')).attr('id', 'cal-slide-box');
- slider.hide().click(function(event) {
- event.stopPropagation();
- });
- this._loadTemplate('events-list');
- downbox.click(function(event) {
- showEventsList(event, $(this), slider, self);
- });
- };
- Calendar.prototype.getEventsBetween = function(start, end) {
- var events = [];
- $.each(this.options.events, function() {
- if(this.start == null) {
- return true;
- }
- var event_end = this.end || this.start;
- if((parseInt(this.start) < end) && (parseInt(event_end) >= start)) {
- events.push(this);
- }
- });
- return events;
- };
- function showEventsList(event, that, slider, self) {
- event.stopPropagation();
- var that = $(that);
- var cell = that.closest('.cal-cell');
- var row = cell.closest('.cal-before-eventlist');
- var tick_position = cell.data('cal-row');
- that.fadeOut('fast');
- slider.slideUp('fast', function() {
- var event_list = $('.events-list', cell);
- slider.html(self.options.templates['events-list']({
- cal: self,
- events: self.getEventsBetween(parseInt(event_list.data('cal-start')), parseInt(event_list.data('cal-end')))
- }));
- row.after(slider);
- self.activecell = $('[data-cal-date]', cell).text();
- $('#cal-slide-tick').addClass('tick' + tick_position).show();
- slider.slideDown('fast', function() {
- $('body').one('click', function() {
- slider.slideUp('fast');
- self.activecell = 0;
- });
- });
- });
- // Wait 400ms before updating the modal & attach the mouseenter&mouseleave(400ms is the time for the slider to fade out and slide up)
- setTimeout(function() {
- $('a.event-item').mouseenter(function() {
- $('a[data-event-id="' + $(this).data('event-id') + '"]').closest('.cal-cell1').addClass('day-highlight dh-' + $(this).data('event-class'));
- });
- $('a.event-item').mouseleave(function() {
- $('div.cal-cell1').removeClass('day-highlight dh-' + $(this).data('event-class'));
- });
- self._update_modal();
- }, 400);
- }
- function getEasterDate(year, offsetDays) {
- var a = year % 19;
- var b = Math.floor(year / 100);
- var c = year % 100;
- var d = Math.floor(b / 4);
- var e = b % 4;
- var f = Math.floor((b + 8) / 25);
- var g = Math.floor((b - f + 1) / 3);
- var h = (19 * a + b - d - g + 15) % 30;
- var i = Math.floor(c / 4);
- var k = c % 4;
- var l = (32 + 2 * e + 2 * i - h - k) % 7;
- var m = Math.floor((a + 11 * h + 22 * l) / 451);
- var n0 = (h + l + 7 * m + 114)
- var n = Math.floor(n0 / 31) - 1;
- var p = n0 % 31 + 1;
- return new Date(year, n, p + (offsetDays ? offsetDays : 0), 0, 0, 0);
- }
- $.fn.calendar = function(params) {
- return new Calendar(params, this);
- }
- }(jQuery));
|