// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) // // MIT License (MIT) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // pscript.onload_calendar = function(wrapper) { if(!erpnext.calendar) { erpnext.calendar = new Calendar(); erpnext.calendar.init(wrapper); rename_observers.push(erpnext.calendar); } } ///// CALENDAR Calendar=function() { this.views=[]; this.events = {}; this.events_by_name = {}; this.weekdays = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat"); } Calendar.prototype.init=function (parent) { this.wrapper = parent; this.body = $('.cal_body').get(0); //this.make_head_buttons(); //this.make_header(); this.view_title = $('.cal_view_title').get(0); this.todays_date = new Date(); this.selected_date = this.todays_date; this.selected_hour = 8; // Create views this.views['Month'] = new Calendar.MonthView(this); this.views['Week'] = new Calendar.WeekView(this); this.views['Day'] = new Calendar.DayView(this); // Month view as initial this.cur_view = this.views['Month']; this.views['Month'].show(); } Calendar.prototype.rename_notify = function(dt, old_name, new_name) { // calendar if(dt = 'Event'){ if(this.events_by_name[old_name]) { delete this.events_by_name[old_name]; } } } //------------------------------------------------------ Calendar.prototype.show_event = function(ev, cal_ev) { var me = this; if(!this.event_dialog) { var d = new Dialog(400, 400, 'Calendar Event'); d.make_body([ ['HTML','Heading'] ,['Text','Description'] ,['Check', 'Public Event'] ,['Check', 'Cancel Event'] ,['HTML', 'Event Link'] ,['Button', 'Save'] ]) // show the event when the dialog opens d.onshow = function() { // heading var c = me.selected_date; var tmp = time_to_ampm(this.ev.event_hour); tmp = tmp[0]+':'+tmp[1]+' '+tmp[2]; this.widgets['Heading'].innerHTML = '
' + erpnext.calendar.weekdays[c.getDay()] + ', ' + c.getDate() + ' ' + month_list_full[c.getMonth()] + ' ' + c.getFullYear() + ' - '+tmp+'
'; // set this.widgets['Description'].value = cstr(this.ev.description); this.widgets['Public Event'].checked = false; this.widgets['Cancel Event'].checked = false; if(this.ev.event_type=='Public') this.widgets['Public Event'].checked = true; this.widgets['Event Link'].innerHTML = ''; // link var div = $a(this.widgets['Event Link'], 'div', 'link_type', {margin:'4px 0px'}); div.onclick = function() { me.event_dialog.hide(); loaddoc('Event', me.event_dialog.ev.name); } div.innerHTML = 'View Event details, add or edit participants'; } // event save d.widgets['Save'].onclick = function() { var d = me.event_dialog; // save values d.ev.description = d.widgets['Description'].value; if(d.widgets['Cancel Event'].checked) d.ev.event_type='Cancel'; else if(d.widgets['Public Event'].checked) d.ev.event_type='Public'; me.event_dialog.hide(); // if new event me.save_event(d.ev); } this.event_dialog = d; } this.event_dialog.ev = ev; this.event_dialog.cal_ev = cal_ev ? cal_ev : null; this.event_dialog.show(); } Calendar.prototype.save_event = function(doc) { var me = this; save_doclist('Event', doc.name, 'Save', function(r) { var doc = locals['Event'][r.docname]; var cal = erpnext.calendar; cal.cur_view.refresh(); // if cancelled, hide if(doc.event_type=='Cancel') { $(cal.events_by_name[doc.name].body).toggle(false); } }); } //------------------------------------------------------ Calendar.prototype.add_event = function() { var ev = LocalDB.create('Event'); ev = locals['Event'][ev]; ev.event_date = dateutil.obj_to_str(this.selected_date); ev.event_hour = this.selected_hour+':00'; ev.event_type = 'Private'; this.show_event(ev); } //------------------------------------------------------ Calendar.prototype.get_month_events = function(call_back) { // ret fn var me = this; var f = function(r, rt) { if(me.cur_view) me.cur_view.refresh(); if(call_back)call_back(); } //load var y=this.selected_date.getFullYear(); var m = this.selected_date.getMonth(); if(!this.events[y] || !this.events[y][m]) { $c('webnotes.widgets.event.load_month_events', args = { 'month': m + 1, 'year' : y}, f); } } //------------------------------------------------------ Calendar.prototype.get_daily_event_list=function(day) { var el = []; var d = day.getDate(); var m = day.getMonth(); var y = day.getFullYear() if(this.events[y] && this.events[y][m] && this.events[y][m][d]) { var l = this.events[y][m][d] for(var i in l) { for(var j in l[i]) el[el.length] = l[i][j]; } return el; } else return []; } //------------------------------------------------------ Calendar.prototype.set_event = function(ev) { // don't duplicate if(this.events_by_name[ev.name]) { return this.events_by_name[ev.name]; } var dt = dateutil.str_to_obj(ev.event_date); var m = dt.getMonth(); var d = dt.getDate(); var y = dt.getFullYear(); if(!this.events[y]) this.events[y] = []; if(!this.events[y][m]) this.events[y][m] = []; if(!this.events[y][m][d]) this.events[y][m][d] = []; if(!this.events[y][m][d][cint(ev.event_hour)]) this.events[y][m][d][cint(ev.event_hour)] = []; var cal_ev = new Calendar.CalEvent(ev, this); this.events[y][m][d][cint(ev.event_hour)].push(cal_ev); this.events_by_name[ev.name] = cal_ev; return cal_ev; } //------------------------------------------------------ Calendar.prototype.refresh = function(viewtype){//Sets the viewtype of the Calendar and Calls the View class based on the viewtype if(viewtype) this.viewtype = viewtype; // switch view if reqd if(this.cur_view.viewtype!=this.viewtype) { this.cur_view.hide(); this.cur_view = this.views[this.viewtype]; this.cur_view.in_home = false; // for home page this.cur_view.show(); } else{ this.cur_view.refresh(this); } } //------------------------------------------------------ Calendar.CalEvent= function(doc, cal) { this.body = document.createElement('div'); this.link = $a(this.body, 'a', '', {}, locals['Event'][doc.name].description || ''); this.doc = doc; var me = this; this.link.onclick = function() { if(me.doc.name) { cal.show_event(me.doc, me); } } } Calendar.CalEvent.prototype.show = function(vu) { var t = this.doc.event_type; this.my_class = 'cal_event_'+ t; if(this.body.parentNode) this.body.parentNode.removeChild(this.body); vu.body.appendChild(this.body); // refresh this.link.innerHTML = this.doc.description || ''; this.body.className = this.my_class; } // ---------- Calendar.View =function() { this.daystep = 0; this.monthstep = 0; } Calendar.View.prototype.init=function(cal) { this.cal = cal; this.body = $a(cal.body, 'div', 'cal_view_body'); this.body.style.display = 'none'; this.create_table(); } Calendar.View.prototype.show=function() { this.get_events(); this.refresh(); this.body.style.display = 'block'; } Calendar.View.prototype.hide=function() { this.body.style.display = 'none';} Calendar.View.prototype.next = function() { var s = this.cal.selected_date; this.cal.selected_date = new Date(s.getFullYear(), s.getMonth() + this.monthstep, s.getDate() + this.daystep); this.get_events(); this.refresh(); } Calendar.View.prototype.prev = function() { var s = this.cal.selected_date; this.cal.selected_date = new Date(s.getFullYear(), s.getMonth() - this.monthstep, s.getDate() - this.daystep); this.get_events(); this.refresh(); } Calendar.View.prototype.get_events = function() { this.cal.get_month_events(); } Calendar.View.prototype.add_unit = function(vu) { this.viewunits[this.viewunits.length] = vu; } Calendar.View.prototype.refresh_units = function() { // load the events if(locals['Event']) { for(var name in locals['Event']) { this.cal.set_event(locals['Event'][name]); } } for(var r in this.table.rows) { for(var c in this.table.rows[r].cells) { if(this.table.rows[r].cells[c].viewunit) { this.table.rows[r].cells[c].viewunit.refresh(); } } } } // ................. Month View.......................... Calendar.MonthView = function(cal) { this.init(cal); this.monthstep = 1; this.rows = 5; this.cells = 7; } Calendar.MonthView.prototype=new Calendar.View(); Calendar.MonthView.prototype.create_table = function() { // create head this.head_wrapper = $a(this.body, 'div', 'cal_month_head'); // create headers this.headtable = $a(this.head_wrapper, 'table', 'cal_month_headtable'); var r = this.headtable.insertRow(0); for(var j=0;j<7;j++) { var cell = r.insertCell(j); cell.innerHTML = erpnext.calendar.weekdays[j]; $w(cell, (100 / 7) + '%'); } this.main = $a(this.body, 'div', 'cal_month_body'); this.table = $a(this.main, 'table', 'cal_month_table'); var me = this; // create body for(var i=0;i<5;i++) { var r = this.table.insertRow(i); for(var j=0;j<7;j++) { var cell = r.insertCell(j); cell.viewunit = new Calendar.MonthViewUnit(cell); } } } Calendar.MonthView.prototype.refresh = function() { var c =this.cal.selected_date; var me=this; // fill other days var cur_row = 0; var cur_month = c.getMonth(); var cur_year = c.getFullYear(); var d = new Date(cur_year, cur_month, 1); var day = 1 - d.getDay(); // set day headers var d = new Date(cur_year, cur_month, day); this.cal.view_title.innerHTML = month_list_full[cur_month] + ' ' + cur_year; for(var i=0;i<6;i++) { if((i<5) || cur_month==d.getMonth()) { // if this month for(var j=0;j<7;j++) { var cell = this.table.rows[cur_row].cells[j]; if((i<5) || cur_month==d.getMonth()) { // if this month cell.viewunit.day = d; cell.viewunit.hour = 8; if(cur_month == d.getMonth()) { cell.viewunit.is_disabled = false; if(same_day(this.cal.todays_date, d)) cell.viewunit.is_today = true; else cell.viewunit.is_today = false; } else { cell.viewunit.is_disabled = true; } } // new date day++; d = new Date(cur_year, cur_month, day); } } cur_row++; if(cur_row == 5) {cur_row = 0;} // back to top } this.refresh_units(); } // ................. Daily View.......................... Calendar.DayView=function(cal){ this.init(cal); this.daystep = 1; } Calendar.DayView.prototype=new Calendar.View(); Calendar.DayView.prototype.create_table = function() { // create body this.main = $a(this.body, 'div', 'cal_day_body'); this.table = $a(this.main, 'table', 'cal_day_table'); var me = this; for(var i=0;i<24;i++) { var r = this.table.insertRow(i); for(var j=0;j<2;j++) { var cell = r.insertCell(j); if(j==0) { var tmp = time_to_ampm((i)+':00'); cell.innerHTML = tmp[0]+':'+tmp[1]+' '+tmp[2]; $w(cell, '10%'); } else { cell.viewunit = new Calendar.DayViewUnit(cell); cell.viewunit.hour = i; $w(cell, '90%'); if((i>=7)&&(i<=20)) { cell.viewunit.is_daytime = true; } } } } } Calendar.DayView.prototype.refresh = function() { var c =this.cal.selected_date; // fill other days var me=this; this.cal.view_title.innerHTML = erpnext.calendar.weekdays[c.getDay()] + ', ' + c.getDate() + ' ' + month_list_full[c.getMonth()] + ' ' + c.getFullYear(); // headers var d = c; for(var i=0;i<24;i++) { var cell = this.table.rows[i].cells[1]; if(same_day(this.cal.todays_date, d)) cell.viewunit.is_today = true; else cell.viewunit.is_today = false; cell.viewunit.day = d; } this.refresh_units(); } // ................. Weekly View.......................... Calendar.WeekView=function(cal) { this.init(cal); this.daystep = 7; } Calendar.WeekView.prototype=new Calendar.View(); Calendar.WeekView.prototype.create_table = function() { // create head this.head_wrapper = $a(this.body, 'div', 'cal_month_head'); // day headers this.headtable = $a(this.head_wrapper, 'table', 'cal_month_headtable'); var r = this.headtable.insertRow(0); for(var j=0;j<8;j++) { var cell = r.insertCell(j); $w(cell, (100 / 8) + '%'); } // hour header // create body this.main = $a(this.body, 'div', 'cal_week_body'); this.table = $a(this.main, 'table', 'cal_week_table'); var me = this; for(var i=0;i<24;i++) { var r = this.table.insertRow(i); for(var j=0;j<8;j++) { var cell = r.insertCell(j); if(j==0) { var tmp = time_to_ampm(i+':00'); cell.innerHTML = tmp[0]+':'+tmp[1]+' '+tmp[2]; $w(cell, '10%'); } else { cell.viewunit = new Calendar.WeekViewUnit(cell); cell.viewunit.hour = i; if((i>=7)&&(i<=20)) { cell.viewunit.is_daytime = true; } } } } } Calendar.WeekView.prototype.refresh = function() { var c =this.cal.selected_date; // fill other days var me=this; this.cal.view_title.innerHTML = month_list_full[c.getMonth()] + ' ' + c.getFullYear(); // headers var d = new Date(c.getFullYear(), c.getMonth(), c.getDate() - c.getDay()); for (var k=1;k<8;k++) { this.headtable.rows[0].cells[k].innerHTML = erpnext.calendar.weekdays[d.getDay()] + ' ' + d.getDate(); for(var i=0;i<24;i++) { var cell = this.table.rows[i].cells[k]; if(same_day(this.cal.todays_date, d)) cell.viewunit.is_today = true; else cell.viewunit.is_today = false; cell.viewunit.day = d; //cell.viewunit.refresh(); } d=new Date(d.getFullYear(),d.getMonth(),d.getDate() + 1); } this.refresh_units(); } //------------------------------------------------------. Calendar.ViewUnit = function() {} Calendar.ViewUnit.prototype.init = function(parent) { parent.style.border = "1px solid #CCC" ; this.body = $a(parent, 'div', this.default_class); this.parent = parent; var me = this; this.body.onclick = function() { erpnext.calendar.selected_date = me.day; erpnext.calendar.selected_hour = me.hour; if(erpnext.calendar.cur_vu && erpnext.calendar.cur_vu!=me){ erpnext.calendar.cur_vu.deselect(); me.select(); erpnext.calendar.cur_vu = me; } } this.body.ondblclick = function() { erpnext.calendar.add_event(); } } Calendar.ViewUnit.prototype.set_header=function(v) { this.header.innerHTML = v; } Calendar.ViewUnit.prototype.set_today = function() { this.is_today = true; this.set_display(); } Calendar.ViewUnit.prototype.clear = function() { if(this.header)this.header.innerHTML = ''; // clear body while(this.body.childNodes.length) this.body.removeChild(this.body.childNodes[0]); } Calendar.ViewUnit.prototype.set_display = function() { var cn = '#FFF'; // colors var col_tod_sel = '#EEE'; var col_tod = '#FFF'; var col_sel = '#EEF'; if(this.is_today) { if(this.selected) cn = col_tod_sel; else cn = col_tod; } else if(this.selected) cn = col_sel; if(this.header) { if(this.is_disabled) { this.body.className = this.default_class + ' cal_vu_disabled'; this.header.style.color = '#BBB'; } else { this.body.className = this.default_class; this.header.style.color = '#000'; } if(this.day&&this.day.getDay()==0) this.header.style.backgroundColor = '#FEE'; else this.header.style.backgroundColor = ''; } this.parent.style.backgroundColor = cn; } Calendar.ViewUnit.prototype.is_selected = function() { return (same_day(this.day, erpnext.calendar.selected_date) && this.hour==erpnext.calendar.selected_hour) } Calendar.ViewUnit.prototype.get_event_list = function() { var y = this.day.getFullYear(); var m = this.day.getMonth(); var d = this.day.getDate(); if(erpnext.calendar.events[y] && erpnext.calendar.events[y][m] && erpnext.calendar.events[y][m][d] && erpnext.calendar.events[y][m][d][this.hour]) { return erpnext.calendar.events[y][m][d][this.hour]; } else return []; } Calendar.ViewUnit.prototype.refresh = function() { this.clear(); if(this.is_selected()) { if(erpnext.calendar.cur_vu)erpnext.calendar.cur_vu.deselect(); this.selected = true; erpnext.calendar.cur_vu = this; } this.set_display(); this.el = this.get_event_list(); if(this.onrefresh)this.onrefresh(); for(var i in this.el) { this.el[i].show(this); } var me = this; } Calendar.ViewUnit.prototype.select=function() { this.selected = true; this.set_display(); } Calendar.ViewUnit.prototype.deselect=function() { this.selected = false; this.set_display(); } Calendar.ViewUnit.prototype.setevent=function() { } Calendar.MonthViewUnit=function(parent) { this.header = $a(parent, 'div' , "cal_month_date"); this.default_class = "cal_month_unit"; this.init(parent); this.onrefresh = function() { this.header.innerHTML = this.day.getDate(); } } Calendar.MonthViewUnit.prototype = new Calendar.ViewUnit(); Calendar.MonthViewUnit.prototype.is_selected = function() { return same_day(this.day, erpnext.calendar.selected_date) } Calendar.MonthViewUnit.prototype.get_event_list = function() { return erpnext.calendar.get_daily_event_list(this.day); } Calendar.DayViewUnit= function(parent) { this.default_class = "cal_day_unit"; this.init(parent); } Calendar.DayViewUnit.prototype = new Calendar.ViewUnit(); Calendar.DayViewUnit.prototype.onrefresh = function() { if(this.el.length<3) this.body.style.height = '30px'; else this.body.style.height = ''; } Calendar.WeekViewUnit=function(parent) { this.default_class = "cal_week_unit"; this.init(parent); } Calendar.WeekViewUnit.prototype = new Calendar.ViewUnit(); Calendar.WeekViewUnit.prototype.onrefresh = function() { if(this.el.length<3) this.body.style.height = '30px'; else this.body.style.height = ''; }