diff --git a/app/assets/javascripts/calendar.js b/app/assets/javascripts/calendar.js index 54017e9..9ffdd24 100644 --- a/app/assets/javascripts/calendar.js +++ b/app/assets/javascripts/calendar.js @@ -1,26 +1,131 @@ +window.auto_close_popup = false; +$.fn.fullCalendar = function(args){ + var self = this[0] + if(!self.calendar_args) + self.calendar_args = args; + else + args = Object.assign(self.calendar_args, args); + var calendar = new FullCalendar.Calendar(self,args); + calendar.render(); + $(window).on("load",function(){ + calendar.render(); + }) + this.calendar = calendar; + self.calendar = calendar; + $.fullCalendar = calendar; + return calendar; +}; +function correct_date(date){ + var new_date = new Date(); + new_date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000); + return new_date; +} +FullCalendar.Calendar.prototype.get_all_events = function(){ + this.currentData.all_events = []; + var all_events = this.currentData.all_events; + if(this.currentData.eventStore && this.currentData.eventStore.instances){ + var instances = this.currentData.eventStore.instances; + Object.keys(instances).forEach(function(k){ + var instance = instances[k]; + var range = Object.assign({},instance.range); + range.start = correct_date(range.start); + range.end = correct_date(range.end); + all_events.push(range); + }) + } + return this.currentData.all_events; +} +FullCalendar.Calendar.prototype.isAnOverlapEvent = function(eventStartDay, eventEndDay){ + eventStartDay = eventStartDay || eventEndDay; + eventEndDay = eventEndDay || eventStartDay; + if((typeof(eventStartDay)).toLowerCase() == "string") + eventStartDay = new Date(eventStartDay); + if((typeof(eventEndDay)).toLowerCase() == "string") + eventEndDay = new Date(eventEndDay); + var events = this.get_all_events(); + for (var i = 0; i < events.length; i++) { + var eventA = events[i]; + // start-time in between any of the events + if (eventStartDay >= eventA.start && eventStartDay <= eventA.end) { + return true; + } + //end-time in between any of the events + if (eventEndDay >= eventA.start && eventEndDay <= eventA.end) { + return true; + } + //any of the events in between/on the start-time and end-time + if (eventStartDay <= eventA.start && eventEndDay >= eventA.end) { + return true; + } + } + return false; +} +window.is_chinese = ( I18n && I18n.locale.indexOf('zh') != -1 ); +window.datetime_format = is_chinese ? 'y M d h:m b' : 'd M, y h:m b'; +window.date_format = is_chinese ? 'y M d' : 'd M, y'; +window.datetime_format = window.date_format; +window.time_format = "h:m b"; +window.std_date_format = 'y-MM-d'; +window.short_day = (is_chinese ? "d (w)" : "w d"); +window.short_date = (is_chinese ? "M d (w)" : "w d, M"); +window.short_date_time = (is_chinese ? "M d (w) h:m b" : "w d, M h:m b"); +window.getDateString = function(date, format,is_chinese) { + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + var week_days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; + if(is_chinese){ + months = []; + for(var i=0;i<12;i++){ + months.push((i+1)+"月"); + } + week_days = ["週日","週一","週二","週三","週四","週五","週六"] + } + var getPaddedComp = function(comp) { + return ((parseInt(comp) < 10) ? ('0' + comp) : comp) + }, + formattedDate = format, + o = { + "y+": date.getFullYear() + (is_chinese ? "年" : ""), // year + "MM+": getPaddedComp(date.getMonth() + 1), //raw month + "M+": months[date.getMonth()], //month + "d+": (is_chinese ? (date.getDate() + "日") : getPaddedComp(date.getDate())), //day + "w+": week_days[date.getDay()], //weekday + "h+": getPaddedComp((date.getHours() > 12) ? date.getHours() % 12 : date.getHours()), //hour + "H+": getPaddedComp(date.getHours()), //hour + "m+": getPaddedComp(date.getMinutes()), //minute + "s+": getPaddedComp(date.getSeconds()), //second + "S+": getPaddedComp(date.getMilliseconds()), //millisecond, + "b+": (date.getHours() >= 12) ? 'PM' : 'AM' + }; + + for (var k in o) { + if (new RegExp("(" + k + ")").test(format)) { + formattedDate = formattedDate.replace(RegExp.$1, o[k]); + } + } + return formattedDate; +}; var Calendar = function(dom){ - c = this; + var c = this; this.create_event_btn = $("#create_event_btn"); this.event_create_space = $("#event_create_space"); + this.mousePosition = {}; this.title = $("#current_title"); - this.calendar = $(dom); + this.calendar_dom = $(dom); this.nextBtn = $("#next_month_btn"); this.prevBtn = $("#prev_month_btn"); this.todayBtn = $("#today_btn"); this.modeBtns = $(".calendar_mode button"); this.refreshBtn = $("#refresh_btn"); - this.mousePosition = {}; this.dialog = new EventDialog(c); this.loading = $('#calendar-loading'); - this.success_event = null; this.agenda_space = $("#calendar_agenda"); - this.currentView = "month"; + this.currentView = "dayGridMonth"; this.navigation = $("#navigation"); this.rangeSelection = $("#range_selection"); var agendaView = new AgendaView(c); var loadeventsonviewchange = false; - + this.success_event = null; this.initialize = function(){ var date = new Date(); var d = date.getDate(); @@ -28,8 +133,8 @@ var Calendar = function(dom){ var y = date.getFullYear(); var change_event = function(_event, delta) { _event.end = (_event.end ? _event.end : _event.start); - var s = $.fullCalendar.parseDate(c.calendar.find(".fc-view table tbody td:first").data("date")); - var e = $.fullCalendar.parseDate(c.calendar.find(".fc-view table tbody td:first").data("date")); + var s = $.fullCalendar.parseDate(c.calendar_dom.find(".fc-view table tbody td:first").data("date")); + var e = $.fullCalendar.parseDate(c.calendar_dom.find(".fc-view table tbody td:first").data("date")); $.ajax({ url: "/admin/calendars/"+_event.id, // data: {event:{id:_event.id,start:_event.start,end: _event.end,_s:Math.round(+s / 1000), _e:Math.round(+e / 1000)}}, @@ -37,9 +142,9 @@ var Calendar = function(dom){ type: 'put' , datatype: 'JSON', error: function(jqXHR, textStatus, errorThrown) {}, - success: function(data) { - console.log('event was success updated'); - } + success: function(data) { + console.log('event was success updated'); + } }); } var success_event = function(data,allDay,type,addbtn){ @@ -102,12 +207,12 @@ var Calendar = function(dom){ pickers.eq(i).val(value + " " + d.getHours() + ":" + d.getMinutes()) } pickers.eq(i).ui_datetimepicker({ - dateFormat: 'yy/mm/dd', - controlType: 'select', - timeInput: true, - oneLine: true, - timeFormat: 'HH:mm' - }) + dateFormat: 'yy/mm/dd', + controlType: 'select', + timeInput: true, + oneLine: true, + timeFormat: 'HH:mm' + }) } } } @@ -144,7 +249,7 @@ var Calendar = function(dom){ if(type == "new") c.renderEvent(data); if(type == "edit") - c.calendar.fullCalendar("refetchEvents"); + c.calendar_dom.fullCalendar("refetchEvents"); }); c.event_create_space.find("#event_period").change(function(){ //repeat_function(); @@ -152,36 +257,66 @@ var Calendar = function(dom){ //repeat_function(); } c.success_event = success_event; - var dview = (c.currentView == "agenda" ? "month" : c.currentView); - c.calendar.fullCalendar({ - editable: true, + var dview = (c.currentView == "agenda" ? "dayGridMonth" : c.currentView); + c.calendar_dom.css("overflow","visible"); + c.calendar_dom.fullCalendar({ + themeSystem: 'bootstrap', + editable: false, selectable: true, - events: window.location.href, - eventResize: change_event, - eventDrop: change_event , - header: false, - default: dview, + width: "100%", height: $(window).height() - 315, + events: function(args, success_callback, fail_callback) { + var start = args.start; + var end = args.end; + $.ajax({ + url: window.location.href, + dataType: 'json', + type: 'GET', + data: { + start: Math.round(start.getTime() / 1000), + end: Math.round(end.getTime() / 1000), + _: Date.now() + }, + success: function(json) { + // json = json.map(function(obj){ + // obj.start = new Date(obj.start).toJSON(); + // obj.end = new Date(obj.end).toJSON(); + // return obj; + // }) + success_callback(json); + } + }); + }, + // events: 'https://fullcalendar.io/demo-events.json', + headerToolbar: false, + fixedWeekCount: false, + initialView: dview, loading: function(bool) { - if (bool) c.loading.css("left",($(window).width()/2 - 60) + "px").show(); + if (bool) c.loading.show(); else c.loading.hide(); + if(this.currentData) + $('#current_title').html(this.currentData.viewTitle); }, windowResize : function(view){ - view.setHeight($(window).height() - 315); - c.calendar.fullCalendar("refetchEvents"); + c.calendar_dom.calendar.refetchEvents(); }, - viewDisplay: function(view) { - c.title.html(view.title); - }, - eventClick: function(calEvent, e, view) { - c.event_create_space.html("").hide(); - c.dialog.dismiss(); - c.dialog.inflate(calEvent); - c.dialog.show({"x":e.originalEvent.clientX,"y":e.originalEvent.clientY}); - }, - select : function(startDate, endDate, allDay, jsEvent, view){ - var start = new Date(startDate), - end = new Date(endDate), + eventTimeFormat: { hour12: true, hour: '2-digit', minute: '2-digit', omitZeroMinute: true, meridiem: 'narrow' }, + eventClick: function(eventClickInfo) { + var calEvent = {"event": eventClickInfo.event}, + originalEvent = eventClickInfo.jsEvent, + view = eventClickInfo.view, + el = $(eventClickInfo.el); + c.event_create_space.html("").hide(); + c.dialog.dismiss(); + c.dialog.inflate(calEvent); + c.dialog.show({"x": originalEvent.clientX,"y": originalEvent.clientY}); + }, + select : function(selectionInfo){ + var jsEvent = selectionInfo.jsEvent, + view = selectionInfo.view; + var start = selectionInfo.start, + end = selectionInfo.end, + allDay = selectionInfo.allDay, startString = start.getFullYear() + "/"+ (start.getMonth() + 1 > 9 ? start.getMonth() + 1 : "0" + (start.getMonth() + 1)) + "/" + (start.getDate() > 9 ? start.getDate() : "0" + start.getDate()), endString = end.getFullYear() + "/" + (end.getMonth() + 1 > 9 ? end.getMonth() + 1 : "0" + (end.getMonth() + 1)) + "/" + (end.getDate() > 9 ? end.getDate() : "0" + end.getDate()); @@ -193,15 +328,20 @@ var Calendar = function(dom){ endString += " " + end.getMinutes() + ":" + end.getMinutes(); } - $.ajax({ - type : "get", - url : c.create_event_btn.attr("href"), - data : {"startDate":startString,"endDate":endString,"allDay":allDay}, - success : function(data){ - success_event(data,allDay,"new"); - } - }) - } + $.ajax({ + type : "get", + url : c.create_event_btn.attr("href"), + data : {"startDate":startString,"endDate":endString,"allDay":allDay}, + success : function(data){ + success_event(data,allDay,"new"); + } + }) + }, + views: { + dayGridMonth: { + dayMaxEvents: false + } + } }); c.create_event_btn.click(function(){ $.ajax({ @@ -215,19 +355,18 @@ var Calendar = function(dom){ }); c.nextBtn.click(function(){ c.dialog.dismiss(); - c.calendar.fullCalendar('next'); + c.calendar_dom.calendar.next(); }); c.prevBtn.click(function(){ c.dialog.dismiss(); - c.calendar.fullCalendar('prev'); + c.calendar_dom.calendar.prev(); }); c.todayBtn.click(function(){ c.dialog.dismiss(); - c.calendar.fullCalendar('today'); + c.calendar_dom.calendar.today(); }); c.modeBtns.click(function(){ c.dialog.dismiss(); - c.event_create_space.html("").hide(); toggleViews($(this).data("mode")); }); c.refreshBtn.click(function(){ @@ -235,18 +374,17 @@ var Calendar = function(dom){ if(c.currentView == "agenda") agendaView.refresh(); else - c.calendar.fullCalendar("refetchEvents"); + c.calendar_dom.calendar.refetchEvents(); }); - c.calendar.mouseup(function(e){ + c.calendar_dom.mouseup(function(e){ c.mousePosition = {"x" : e.pageX, "y" : e.pageY}; }) - var toggleViews = function(view){ c.modeBtns.removeClass("active"); c.modeBtns.each(function(){ if ($(this).data("mode") == view) $(this).addClass("active"); - }) + }); if(view != "agenda"){ if(c.currentView == "agenda"){ // $("#sec1").addClass("span3").removeClass("span7"); @@ -254,7 +392,7 @@ var Calendar = function(dom){ // $("#sec3").addClass("span4").removeClass("span5"); agendaView.hide(); } - c.calendar.fullCalendar('changeView',view); + c.calendar_dom.calendar.changeView(view); }else{ // $("#sec1").addClass("span7").removeClass("span3"); $("#sec2").hide(); @@ -263,47 +401,22 @@ var Calendar = function(dom){ } c.currentView = view; if(loadeventsonviewchange){ - c.calendar.fullCalendar("refetchEvents"); + c.calendar_dom.calendar.refetchEvents(); loadeventsonviewchange = false; } - } + if(c.calendar_dom.calendar.currentData){ + var viewTitle = c.calendar_dom.calendar.currentData.viewTitle; + if(view == "timeGridDay" && $('.fc-col-header-cell-cushion ').text() != "") + viewTitle = $('.fc-col-header-cell-cushion ').text() + ', ' + viewTitle; + $('#current_title').html(viewTitle); + } + c.calendar_dom.calendar.render(); //Rerender to fix layout + }; if(c.currentView == "agenda"){toggleViews("agenda");loadeventsonviewchange = true;} - c.calendar.on("DOMMouseScroll mousewheel", function(e){ - if(c.calendar.fullCalendar("getView").name == "month"){ - if(!c.isFormVisible()){ - c.dialog.dismiss(); - if(/Firefox/i.test(navigator.userAgent)){ - if(e.originalEvent.detail == 1){ - c.calendar.fullCalendar('next'); - }else if(e.originalEvent.detail == -1){ - c.calendar.fullCalendar('prev'); - } - }else{ - if(e.originalEvent.wheelDelta /120 > 0) - c.calendar.fullCalendar('prev'); - else - c.calendar.fullCalendar('next'); - } - } - } - }); - - } - - this.isFormVisible = function(){ - return (c.event_create_space.html() == "" ? false : true); - } - - this.renderEvent = function(eventStick){ - if(eventStick.recurring == true){ - c.calendar.fullCalendar("refetchEvents"); - }else{ - c.calendar.fullCalendar("renderEvent",eventStick); - } - } + }; this.updateEvent = function(eventStick){ - c.calendar.fullCalendar("updateEvent",eventStick); + c.calendar_dom.fullCalendar("updateEvent",eventStick); } this.deleteEvent = function(delete_url,_id){ @@ -311,7 +424,7 @@ var Calendar = function(dom){ type : "delete", url : delete_url, success : function(){ - c.calendar.fullCalendar("removeEvents",[_id]); + c.calendar_dom.fullCalendar("removeEvents",[_id]); c.dialog.dismiss(); } }) @@ -328,53 +441,80 @@ var Calendar = function(dom){ }) } + this.renderEvent = function(eventStick){ + if(eventStick.recurring === true) + c.calendar_dom.calendar.refetchEvents(); + else + c.calendar_dom.calendar.addEvent(eventStick); + }; + + $(document).ready(function() { c.initialize(); }); -} +}; var EventDialog = function(calendar,event){ _t = this; var event_quick_view = null; var template = ""; var _this_event = null; - var month_names = ["Jan","Feb","March","April","May","June","July","Aug","Sep","Oct","Nov","Dec"]; this.inflate = function(_event){ if(!_event) throw new UserException("EventStick can't be null!"); + _event.allDay = _event.event.allDay; + _event._start = _event.event.start; + _event._end = (_event.event.end ? _event.event.end : _event.event.start); + // var start_date = getDateString(_event._start,date_format); + // var end_date = getDateString(_event._end,date_format); + if(_event._end - _event._start > 86400 * 1000){ + _event.allDay = true; + } + _event.title = _event.event.title; + var extendedProps = _event.event.extendedProps; + Object.keys(extendedProps).forEach(function(k){ + _event[k] = extendedProps[k]; + }) + if(_event.hiring_person_name == undefined) + _event.hiring_person_name = ""; _this_event = _event; var start_time = "", - end_time = "", - time_string = null; - Event_e = _event + end_time = "", + time_string = null; if(_event.allDay) { - start_time = $.fullCalendar.formatDate(_event._start,"MMM dd, yyyy"); + start_time = getDateString(_event._start,datetime_format, is_chinese); if(_event._end) - end_time = $.fullCalendar.formatDate(_event._end,"MMM dd, yyyy"); - time_string = (_event._start === _event._end || !_event._end ? "

" + start_time + "

" : " " + start_time + " " + end_time + ""); + end_time = getDateString(_event._end,datetime_format, is_chinese); + time_string = (_event._start === _event._end || !_event._end ? "

" + start_time + "

" : "" + start_time + "
" + end_time + ""); } else { - var sh = _event._start.getHours() > 12 ? _event._start.getHours() - 12 : _event._start.getHours(), - eh = _event._end.getHours() > 12 ? _event._end.getHours() - 12 : _event._end.getHours(), - sm = _event._start.getMinutes() < 10 ? '0' + _event._start.getMinutes() : _event._start.getMinutes(), - em = _event._end.getMinutes() < 10 ? '0' + _event._end.getMinutes() : _event._end.getMinutes(), - stime = _event._start.getHours() > 12 ? sh + ':' + sm + " PM" : sh + ':' + sm + " AM", - etime = _event._end.getHours() > 12 ? eh + ':' + em + " PM" : eh + ':' + em + " AM", - same = (_event._start.getDate() == _event._end.getDate() && _event._start.getMonth() == _event._end.getMonth() && _event._start.getFullYear() == _event._end.getFullYear()); - start_time = month_names[_event._start.getMonth()] + " " + _event._start.getDate() + ", " + _event._start.getFullYear(); - end_time = month_names[_event._end.getMonth()] + " " + _event._end.getDate() + ", " + _event._end.getFullYear(); - - time_string = (same ? "

" + start_time + "

" + stime + " " + etime : "

" + start_time + "" + stime + "

" + end_time + "" + etime + "

"); + start_time = getDateString(_event._start,date_format, is_chinese); + end_time = getDateString(_event._end,date_format, is_chinese); + var stime = getDateString(_event._start,time_format, is_chinese), + etime = getDateString(_event._end,time_format, is_chinese), + same = (start_time == end_time); + if( same ){ + time_string = "

" + + start_time + + "

" + stime + + " " + etime ; + }else{ + time_string = "" + start_time + " " + stime + + "
" + + end_time + " " + etime + "" + } + // time_string = (same ? "

" + start_time + "

" + stime + " " + etime : "

" + start_time + "" + stime + "

" + end_time + "" + etime + "

"); } - event_quick_view = $(''); - template = '