initial commit

master
Harry Bomrah 9 years ago
commit e3aefb4879

@ -0,0 +1,17 @@
source "https://rubygems.org"
# Declare your gem's dependencies in calendar.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# jquery-rails is used by the dummy application
gem "jquery-rails"
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
# To use debugger
# gem 'debugger'

@ -0,0 +1,20 @@
Copyright 2014 YOURNAME
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.

@ -0,0 +1,3 @@
= Calendar
This project rocks and uses MIT-LICENSE.

@ -0,0 +1,38 @@
#!/usr/bin/env rake
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
begin
require 'rdoc/task'
rescue LoadError
require 'rdoc/rdoc'
require 'rake/rdoctask'
RDoc::Task = Rake::RDocTask
end
RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'Calendar'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end
Bundler::GemHelper.install_tasks
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
task :default => :test

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because it is too large Load Diff

@ -0,0 +1,742 @@
var Calendar = function(dom){
c = this;
this.create_event_btn = $("#create_event_btn");
this.event_create_space = $("#event_create_space");
this.title = $("#current_title");
this.calendar = $(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.navigation = $("#navigation");
this.rangeSelection = $("#range_selection");
var agendaView = new AgendaView(c);
var loadeventsonviewchange = false;
this.initialize = function(){
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
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"));
$.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)}},
data: {event:{id:_event.id,start:_event.start,end: _event.end}},
type: 'put' ,
datatype: 'JSON',
error: function(jqXHR, textStatus, errorThrown) {},
success: function(data) {
console.log('event was success updated');
}
});
}
var success_event = function(data,allDay,type,addbtn){
c.dialog.dismiss();
c.event_create_space.html(data);
var create_space_height = c.event_create_space.height(),
create_space_width = c.event_create_space.width();
if((create_space_height + c.mousePosition["y"]) >= $(window).height()){
c.event_create_space.css("top",(c.mousePosition["y"] - create_space_height) + "px");
}else{
c.event_create_space.css("top",c.mousePosition["y"] + "px");
}
if((create_space_width + c.mousePosition["x"]) >= $(window).width()){
c.event_create_space.css("left",(c.mousePosition["x"] - create_space_width) + "px");
}else{
c.event_create_space.css("left",c.mousePosition["x"] + "px");
}
if(addbtn){
c.event_create_space.css({"right":"8px","bottom":"50px","left":"auto","top":"auto"});
}else{
c.event_create_space.css({"right":"","bottom":""});
}
c.event_create_space.show();
var dtpick = $('.datetimepick');
var pickers = new Array();
var checked = ($("#all_day_check").is(":checked") ? true : false);
var checked_function = function(c){
if(c){
for(i in pickers){
var input = pickers[i].find("input");
input.val(input.val().split(" ")[0]);
}
}else{
for(i in pickers){
var d = new Date();
var input = pickers[i].find("input");
if(input.val())
input.val(input.val() + " " + d.getHours() + ":" + d.getMinutes());
}
}
}
var repeat_function = function(){
if(c.event_create_space.find("#event_period").val() == c.event_create_space.find("#event_period option:eq(0)").val()){
c.event_create_space.find("#event_frequency").attr("disabled","disabled");
}else{
c.event_create_space.find("#event_frequency").removeAttr("disabled");
}
}
dtpick.each(function() {
var $data = $(this).data();
var options = {
format: $data.dateFormat,
pickTime: $data.picktime,
language: $data.language,
place: "top"
}
pickers.push(
$(this).datetimepicker(options)
);
});
$("a.btn-close").one("click",function(){
c.event_create_space.html("").hide();
return false;
});
$("#all_day_check").click(function(){
if($(this).is(":checked")){
checked = true;
}else{
checked = false;
}
checked_function(checked);
});
$("#recurring_checkbox").click(function(){
if($(this).is(":checked"))
$("#recurring_panel").show();
else
$("#recurring_panel").hide();
})
$('form[data-remote]').bind("ajax:success",function(evt, data, status){
c.event_create_space.html("").hide();
if(type == "new")
c.renderEvent(data);
if(type == "edit")
c.calendar.fullCalendar("refetchEvents");
});
c.event_create_space.find("#event_period").change(function(){
repeat_function();
})
for(i in pickers){
pickers[i].on("changeDate",function(e){
if(checked){
var input = $(this).find("input");
input.val(input.val().split(" ")[0]);
}
})
}
repeat_function();
if(allDay)
checked_function(checked);
}
c.success_event = success_event;
var dview = (c.currentView == "agenda" ? "month" : c.currentView);
c.calendar.fullCalendar({
editable: true,
selectable: true,
events: "/admin/calendars/",
eventResize: change_event,
eventDrop: change_event ,
header: false,
default: dview,
height: $(window).height() - 315,
loading: function(bool) {
if (bool) c.loading.css("left",($(window).width()/2 - 60) + "px").show();
else c.loading.hide();
},
windowResize : function(view){
view.setHeight($(window).height() - 315);
c.calendar.fullCalendar("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),
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());
if(!allDay){
startString += " " + (start.getHours() > 9 ? start.getHours() : "0" + start.getHours()) + ":" + (start.getMinutes() > 9 ? start.getMinutes() : "0" + start.getMinutes());
endString += " " + (end.getHours() > 9 ? end.getHours() : "0" + end.getHours()) + ":" + (end.getMinutes() > 9 ? end.getMinutes() : "0" + end.getMinutes());
}else{
startString += " " + start.getHours() + ":" + start.getMinutes();
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");
}
})
}
});
c.create_event_btn.click(function(){
$.ajax({
type : "get",
url : $(this).attr("href"),
success : function(data){
success_event(data,false,"new",true);
}
})
return false;
});
c.nextBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('next');
});
c.prevBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('prev');
});
c.todayBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('today');
});
c.modeBtns.click(function(){
c.dialog.dismiss();
c.event_create_space.html("").hide();
toggleViews($(this).data("mode"));
});
c.refreshBtn.click(function(){
c.dialog.dismiss();
if(c.currentView == "agenda")
agendaView.refresh();
else
c.calendar.fullCalendar("refetchEvents");
});
c.calendar.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");
$("#sec2").show();
$("#sec3").addClass("span4").removeClass("span5");
agendaView.hide();
}
c.calendar.fullCalendar('changeView',view);
}else{
$("#sec1").addClass("span7").removeClass("span3");
$("#sec2").hide();
$("#sec3").addClass("span5").removeClass("span4");
agendaView.inflate();
}
c.currentView = view;
if(loadeventsonviewchange){
c.calendar.fullCalendar("refetchEvents");
loadeventsonviewchange = false;
}
}
if(c.currentView == "agenda"){toggleViews("agenda");loadeventsonviewchange = true;}
$(document).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);
}
this.deleteEvent = function(delete_url,_id){
$.ajax({
type : "delete",
url : delete_url,
success : function(){
c.calendar.fullCalendar("removeEvents",[_id]);
c.dialog.dismiss();
}
})
}
this.editEvent = function(edit_url,allDay){
$.ajax({
type : "get",
url : edit_url,
success : function(data){
c.success_event(data,allDay,"edit",true);
c.dialog.dismiss();
}
})
}
$(document).ready(function() {
c.initialize();
});
}
var EventDialog = function(calendar,event){
_t = this;
var event_quick_view = null;
var template = "";
var _this_event = null;
this.inflate = function(_event){
if(!_event) throw new UserException("EventStick can't be null!");
_this_event = _event;
var start_time = "",
end_time = "",
time_string = null;
if(_event.allDay){
start_time = (/00:00:00/i.test(_event._start.toLocaleString()) ? $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy hh:mm"));
if(_event._end)
end_time = (/00:00:00/i.test(_event._end.toLocaleString()) ? $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy hh:mm"));
time_string = (_event._start === _event._end || !_event._end ? start_time : start_time + " - " + end_time);
}else{
var reg = new RegExp(/ [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/),
stime = _event._start.toLocaleString().split(",")[1],
etime = _event._end.toLocaleString().split(",")[1];
start_time = _event._start.toLocaleString().replace(stime,"");
end_time = _event._end.toLocaleString().replace(etime,"");
stime = stime.substr(0,stime.length - 3);
etime = etime.substr(0,etime.length - 3);
time_string = (start_time === end_time ? start_time + " " + stime + " - " + etime : start_time + " " + stime + " - " + end_time + " " +etime );
}
event_quick_view = $('<div class="modal" style="width: 300px; display:none; margin:0 0 0 0;"></div>');
template = '<div class="modal-header"><button type="button" class="close event-close-btn" data-dismiss="modal" aria-hidden="true">&times;</button><h3>'+ _event.title +'</h3></div><div class="modal-body"><div class="event_summary">'+ time_string +'</div>'+ _event.note +'</div><div class="modal-footer"><a href="'+ _event.delete_url +'" class="delete btn btn-primary">Delete</a><a href="'+ _event.edit_url +'" class="edit btn btn-primary" >Edit</a></div>';
}
this.show = function(pos){
if(pos){
var pos = getPosition(pos);
event_quick_view.css({"left":pos.x+"px","top":pos.y+"px"});
}
event_quick_view.html(template).appendTo("body").show();
event_quick_view.find(".event-close-btn").one("click",function(){_t.dismiss();});
event_quick_view.find("a.delete").one("click",function(){calendar.deleteEvent(_this_event.delete_url,_this_event._id);return false;});
event_quick_view.find("a.edit").one("click",function(){calendar.editEvent(_this_event.edit_url,_this_event.allDay);return false;});
}
this.dismiss = function(){
if(event_quick_view)
event_quick_view.remove();
}
var getPosition = function(pos){
var x = pos.x,
y = pos.y,
winheight = $(window).height();
if((x + event_quick_view.width()) > $(window).width()){
x = x - event_quick_view.width();
}
if((y + event_quick_view.height()) > winheight){
y = y - event_quick_view.height();
}
return {"x":x,"y":y};
}
if(event)
_t.inflate(event);
}
var UserException = function(message) {
this.message = message;
this.name = "UserException";
this.toString = function(){
return this.message;
}
}
var AgendaView = function(calendar){
var av = this;
var _calendar = calendar;
var agenda_space = _calendar.agenda_space;
var today = new Date();
var minDifference = 6;
var start_month = today.getMonth();
var start_year = today.getFullYear();
var end_month = ((start_month + minDifference) > 11 ? (start_month + minDifference) - 11 : start_month + minDifference);
var end_year = ((start_month + minDifference) > 11 ? start_year+1 : start_year);
var monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December'];
var month_template = '<div class="span4"><h4></h4><div class="tiny_calendar"><table class="table"><tbody><tr><th class="week_title">Sun</th><th class="week_title">Mon</th><th class="week_title">Tue</th><th class="week_title">Wed</th><th class="week_title">Thu</th><th class="week_title">Fri</th><th class="week_title">Sat</th></tr></tbody></table></div></div>';
var event_list_template = '<div class="span8"><table class="table event_list"><thead><tr height="0"><th class="span3"></th><th class="span2"></th><th class=""></th></tr></thead><tbody><tr><td colspan="3" class="no_events">No events for this month.</td></tr></tbody></table></div>';
var head_template = '<div><label>From</label> <select name="start_month" class="input-small"></select><select name="start_year" class="input-small"></select><label>To</label> <select name="end_month" class="input-small"></select><select name="end_year" class="input-small"></select><button id="show_events" class="btn bt-filter">Show Events</button></div>';
var event_template = "<tr><th></th><td class='event_time'></td><td><div class='event'></div></td></tr>";
var cache = false;
var show_event_clicked = false;
this.refresh = function(){
av.inflate(true);
}
this.inflate = function(forceInflation){
loading(true);
_calendar.calendar.hide();
_calendar.navigation.hide();
if(!forceInflation){
if(cache){
av.show();
loading(false);
return;
}
}
agenda_space.empty();
if(!show_event_clicked){
_calendar.rangeSelection.empty();
_calendar.rangeSelection.append(renderHead().html()).show();
_calendar.rangeSelection.find("button#show_events").click(function(){
show_event_clicked = true;
start_month = parseInt($("select[name=start_month]").val());
end_month = parseInt($("select[name=end_month]").val());
start_year = parseInt($("select[name=start_year]").val());
end_year = parseInt($("select[name=end_year]").val());
av.inflate(true);
})
}
show_event_clicked = false;
eventsManager();
var s = start_month,
e = end_month
y = start_year;
e = (e > s && start_year == end_year? e : e + 11);
if(end_year > start_year)
e = e + ((end_year - start_year -1) * 12);
else e--;
for(var i = s;i <= e+1; i++){
var m = new Month(s,y);
s++;
if(s > 11){
s = 0;
y++;
}
if(e == 0)
agenda_space.text("Invalid Range of Dates.")
else
agenda_space.append(m.monthDom);
}
loading(false);
}
this.hide = function(){
cache = true;
_calendar.rangeSelection.hide();
agenda_space.hide();
_calendar.navigation.show();
_calendar.calendar.show();
}
this.show = function(){
_calendar.rangeSelection.show();
agenda_space.show();
}
var copyObject = function(x){
return x.clone();
}
var eventsManager = function(){
var url = "/admin/calendars/agenda",
sd = new Date(start_year,start_month,1),
ed = new Date(end_year,end_month+1,0),
usd = Math.round(sd/1000),
ued = Math.round(ed/1000);
$.ajax({
type : "get",
url : url,
data : {"agenda_start":sd.toLocaleString(),"agenda_end":ed.toLocaleString(),"unix_start":usd,"unix_end":ued},
success : function(events){
$.each(events,function(i,e){
var ed = eventDom(e),
s = new Date(e.start),
e = new Date(e.end),
e_m = ((e.getMonth() > s.getMonth() || s.getMonth() == e.getMonth()) && s.getFullYear() == e.getFullYear() ? e.getMonth() : e.getMonth() + 12)
s_m = s.getMonth(),
s_y = s.getFullYear();
if(e.getFullYear() > s.getFullYear())
e_m = e_m + ((e.getFullYear() - s.getFullYear() -1) * 12);
for(var i = s_m; i < e_m + 1; i++){
var temp_ed = copyObject(ed);
var list = agenda_space.find("div[data-month="+s_m+"][data-year="+s_y+"] table.event_list tbody");
list.append(temp_ed);
s_m++;
if(s_m > 11){
s_m = 0;
s_y++;
}
}
if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear()){
var td = agenda_space.find("td[data-date-node="+s.getDate()+"-"+s.getMonth()+"-"+s.getFullYear()+"]");
td.addClass("has_event");
}else{
var timeDiff = Math.abs(e.getTime() - s.getTime()),
diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)),
c_m = s.getMonth(),
c_d = s.getDate(),
c_y = s.getFullYear(),
end_of_c_month = new Date(s.getFullYear(),s.getMonth()+1,0).getDate();
for(var i = 0; i <= diffDays; i++){
var td = agenda_space.find("td[data-date-node="+c_d+"-"+c_m+"-"+c_y+"]");
td.addClass("has_event");
c_d++;
if(c_d > end_of_c_month){
c_d = 1;
c_m++;
if(c_m > 11){
c_m = 0;
c_y++;
}
}
}
}
})
agenda_space.find("table.event_list tbody").each(function(){
if($(this).find("tr").length > 1)
$(this).find("td.no_events").parent().remove();
})
}
})
var eventDom = function(event){
var e_t = $(event_template),
s = new Date(event.start),
e = new Date(event.end),
dateFormat = "";
if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear())
dateFormat = $.fullCalendar.formatDate(s, "ddd dd");
else
dateFormat = $.fullCalendar.formatDates(s, e, "ddd dd, MMM - {ddd dd, MMM}");
e_t.find("th").text(dateFormat);
e_t.find("td.event_time").text((event.allDay ? "All Day" : $.fullCalendar.formatDate(s, "hh:mm")));
e_t.find("div.event").text(event.title).css("color",event.color);
return e_t;
}
}
var loading = function(bool) {
if (bool) _calendar.loading.css("left",($(window).width()/2 - 60) + "px").show();
else _calendar.loading.hide();
}
var renderHead = function(){
var head = $(head_template);
var start_month_select = head.find("select[name=start_month]");
for(var i = 0; i < 12; i++){
var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
if(i == start_month)
option.attr("selected","selected");
start_month_select.append(option);
}
var end_month_select = head.find("select[name=end_month]");
for(var i = 0; i < 12; i++){
var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
if(i == end_month)
option.attr("selected","selected");
end_month_select.append(option);
}
var start_year_select = head.find("select[name=start_year]");
var y = start_year - 5;
for(var i = 0; i < 10; i++){
var option = $("<option value='"+y+"'>"+y+"</option>");
if(y == start_year)
option.attr("selected","selected");
start_year_select.append(option);
y++;
}
var end_year_select = head.find("select[name=end_year]");
y = start_year - 5;
for(var i = 0; i < 10; i++){
var option = $("<option value='"+y+"'>"+y+"</option>");
if(y == end_year)
option.attr("selected","selected");
end_year_select.append(option);
y++;
}
return head;
}
var Month = function(month,year){
_this = this;
this.monthDom = $("<div class='row-fluid' data-year='"+year+"' data-month='"+month+"'></div>");
var template = $(month_template);
var list_template = $(event_list_template);
var firstDay = new Date(year,month,1);
var lastDay = new Date(year,month+1,0);
var last_inserted_date = 1;
var renderMonth = function(){
var num_of_rows = getNumberOfRows(year,month)
for(var i = 0; i < num_of_rows; i++){
var tr = null;
if(i == 0)
tr = makeRow("first");
else if(i == (num_of_rows - 1)){
tr = makeRow("last");
}else{
tr = makeRow("middle");
}
if(tr == null){
break;
}
template.find("table.table tbody").append(tr);
template.find("h4").text(monthNames[firstDay.getMonth()] + " - " + firstDay.getFullYear());
}
_this.monthDom.append(template);
_this.monthDom.append(list_template);
}
function getNumberOfRows(year, month) {
var day = 1,
sat_counter = 0,
sunday_counter = 0,
date = new Date(year, month, day);
while(date.getMonth() === month) {
if(date.getDay() === 0) {
sunday_counter++;
}else if(date.getDay() === 6) {
sat_counter++;
}
day++;
date = new Date(year, month, day);
}
return (sunday_counter == 5 && sat_counter == 5 ? 6 : 5);
}
var makeRow = function(position){
if(last_inserted_date <= lastDay.getDate()){
var row = $("<tr></tr>");
switch (position){
case "first":
for(var i = 0;i < 7;i++){
var td = $("<td></td>");
if(i >= firstDay.getDay()){
td.text(last_inserted_date);
td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
last_inserted_date++;
}
row.append(td);
}
break;
case "middle":
for(var i = 0;i < 7;i++){
var td = $("<td></td>");
td.text(last_inserted_date);
td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
last_inserted_date++;
row.append(td);
}
break;
case "last":
for(var i = 0;i < 7;i++){
var td = $("<td></td>");
if(i <= lastDay.getDay()){
td.text(last_inserted_date);
td.attr("data-date-node",last_inserted_date+"-"+firstDay.getMonth()+"-"+firstDay.getFullYear());
last_inserted_date++;
}
row.append(td);
}
break;
}
}else{
var row = null;
}
return row;
}
renderMonth();
}
}

@ -0,0 +1,42 @@
//= require_tree .
//= require fullcalendar
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
change_event = function(_event, delta) {
console.log("evento" + _event.id);
$.ajax({
url: "events/"+_event.id+'.json',
data: {event:{id:_event.id,start:_event.start,end: _event.end}},
method: 'PUT' ,
datatype: 'JSON',
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus);
},
success: function(data) {
console.log('event was success updated');
}
});
}
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
events: "events/",
eventResize: change_event,
eventDrop: change_event ,
loading: function(bool) {
if (bool) $('#loading').show();
else $('#loading').hide();
}
});
});

@ -0,0 +1,528 @@
var Calendar = function(dom,page_id){
c = this;
this.title = $("#current_title");
this.calendar = $(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.dialog = new EventDialog(c);
this.loading = $('#calendar-loading');
this.agenda_space = $("#calendar_agenda");
this.currentView = "month";
this.page_id = page_id;
this.navigation = $("#navigation");
this.rangeSelection = $("#range_selection");
var agendaView = new AgendaView(c);
var loadeventsonviewchange = false;
this.initialize = function(){
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var dview = (c.currentView == "agenda" ? "month" : c.currentView);
c.calendar.fullCalendar({
editable: false,
selectable: false,
events: "/xhr/calendars/events?page_id="+c.page_id,
header: false,
default: dview,
height: $("body").height() - 141,
loading: function(bool) {
if (bool) c.loading.css("left",($(window).width()/2 - 60) + "px").show();
else c.loading.hide();
},
windowResize : function(view){
view.setHeight($("body").height() - 141);
c.calendar.fullCalendar("refetchEvents");
},
viewDisplay: function(view) {
c.title.html(view.title);
},
eventClick: function(calEvent, e, view) {
c.dialog.dismiss();
c.dialog.inflate(calEvent);
c.dialog.show({"x":e.originalEvent.clientX,"y":e.originalEvent.clientY});
}
});
c.nextBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('next');
});
c.prevBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('prev');
});
c.todayBtn.click(function(){
c.dialog.dismiss();
c.calendar.fullCalendar('today');
});
c.modeBtns.click(function(){
c.dialog.dismiss();
toggleViews($(this).data("mode"));
});
c.refreshBtn.click(function(){
c.dialog.dismiss();
if(c.currentView == "agenda")
agendaView.refresh();
else
c.calendar.fullCalendar("refetchEvents");
});
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");
$("#sec2").show();
$("#sec3").addClass("span4").removeClass("span5");
agendaView.hide();
}
c.calendar.fullCalendar('changeView',view);
}else{
$("#sec1").addClass("span7").removeClass("span3");
$("#sec2").hide();
$("#sec3").addClass("span5").removeClass("span4");
agendaView.inflate();
}
c.currentView = view;
if(loadeventsonviewchange){
c.calendar.fullCalendar("refetchEvents");
loadeventsonviewchange = false;
}
}
if(c.currentView == "agenda"){toggleViews("agenda");loadeventsonviewchange = true;}
}
this.renderEvent = function(eventStick){
if(eventStick.recurring == true)
c.calendar.fullCalendar("refetchEvents");
else
c.calendar.fullCalendar("renderEvent",eventStick);
}
$(document).ready(function() {
c.initialize();
});
}
var EventDialog = function(calendar,event){
_t = this;
var event_quick_view = null;
var template = "";
var _this_event = null;
this.inflate = function(_event){
if(!_event) throw new UserException("EventStick can't be null!");
_this_event = _event;
var start_time = "",
end_time = "",
time_string = null;
if(_event.allDay){
start_time = (/00:00:00/i.test(_event._start.toLocaleString()) ? $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._start,"ddd MMM dd, yyyy hh:mm"));
if(_event._end)
end_time = (/00:00:00/i.test(_event._end.toLocaleString()) ? $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy") : $.fullCalendar.formatDate(_event._end,"ddd MMM dd, yyyy hh:mm"));
time_string = (_event._start === _event._end || !_event._end ? start_time : start_time + " - " + end_time);
}else{
var reg = new RegExp(/ [0-9][0-9]:[0-9][0-9]:[0-9][0-9]/),
stime = _event._start.toLocaleString().split(",")[1],
etime = _event._end.toLocaleString().split(",")[1];
start_time = _event._start.toLocaleString().replace(stime,",");
end_time = _event._end.toLocaleString().replace(etime,",");
stime = stime.substr(0,stime.length - 3);
etime = etime.substr(0,etime.length - 3);
time_string = (start_time === end_time ? start_time + " " + stime + " - " + etime : start_time + " " + stime + " - " + end_time + " " +etime );
}
event_quick_view = $('<div class="modal" style="width: 300px; display:none; margin:0 0 0 0;"></div>');
template = '<div class="modal-header"><button type="button" class="close event-close-btn" data-dismiss="modal" aria-hidden="true">&times;</button><h3>'+ _event.title +'</h3></div><div class="modal-body"><div class="event_summary">'+ time_string +'</div>'+ _event.note +'</div><div class="modal-footer"></div>';
}
this.show = function(pos){
if(pos){
var pos = getPosition(pos);
event_quick_view.css({"left":pos.x+"px","top":pos.y+"px"});
}
event_quick_view.html(template).appendTo("body").show();
event_quick_view.find(".event-close-btn").one("click",function(){_t.dismiss();});
event_quick_view.find("a.delete").one("click",function(){calendar.deleteEvent(_this_event.delete_url,_this_event._id);return false;});
event_quick_view.find("a.edit").one("click",function(){calendar.editEvent(_this_event.edit_url,_this_event.allDay);return false;});
}
this.dismiss = function(){
if(event_quick_view)
event_quick_view.remove();
}
var getPosition = function(pos){
var x = pos.x,
y = pos.y,
winheight = $(window).height();
if((x + event_quick_view.width()) > $(window).width()){
x = x - event_quick_view.width();
}
if((y + event_quick_view.height()) > winheight){
y = y - event_quick_view.height();
}
return {"x":x,"y":y};
}
if(event)
_t.inflate(event);
}
var UserException = function(message) {
this.message = message;
this.name = "UserException";
this.toString = function(){
return this.message;
}
}
var AgendaView = function(calendar){
var av = this;
var _calendar = calendar;
var agenda_space = _calendar.agenda_space;
var today = new Date();
var minDifference = 6;
var start_month = today.getMonth();
var start_year = today.getFullYear();
var end_month = ((start_month + minDifference) > 11 ? (start_month + minDifference) - 11 : start_month + minDifference);
var end_year = ((start_month + minDifference) > 11 ? start_year+1 : start_year);
var monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December'];
var month_template = '<div class="span4"><h4></h4><div class="tiny_calendar"><table class="table"><tbody><tr><th class="week_title">Sun</th><th class="week_title">Mon</th><th class="week_title">Tue</th><th class="week_title">Wed</th><th class="week_title">Thu</th><th class="week_title">Fri</th><th class="week_title">Sat</th></tr></tbody></table></div></div>';
var event_list_template = '<div class="span8"><table class="table event_list"><thead><tr height="0"><th class="span3"></th><th class="span2"></th><th class=""></th></tr></thead><tbody><tr><td colspan="3" class="no_events">No events for this month.</td></tr></tbody></table></div>';
var head_template = '<div><label>From</label> <select name="start_month" class="input-small"></select><select name="start_year" class="input-small"></select><label>To</label> <select name="end_month" class="input-small"></select><select name="end_year" class="input-small"></select><button id="show_events" class="btn bt-filter">Show Events</button></div>';
var event_template = "<tr><th></th><td class='event_time'></td><td><div class='event'></div></td></tr>";
var cache = false;
var show_event_clicked = false;
this.refresh = function(){
av.inflate(true);
}
this.inflate = function(forceInflation){
loading(true);
_calendar.calendar.hide();
_calendar.navigation.hide();
if(!forceInflation){
if(cache){
av.show();
loading(false);
return;
}
}
agenda_space.empty();
if(!show_event_clicked){
_calendar.rangeSelection.empty();
_calendar.rangeSelection.append(renderHead().html()).show();
_calendar.rangeSelection.find("button#show_events").click(function(){
show_event_clicked = true;
start_month = parseInt($("select[name=start_month]").val());
end_month = parseInt($("select[name=end_month]").val());
start_year = parseInt($("select[name=start_year]").val());
end_year = parseInt($("select[name=end_year]").val());
av.inflate(true);
})
}
show_event_clicked = false;
eventsManager();
var s = start_month,
e = end_month
y = start_year;
e = (e > s && start_year == end_year? e : e + 11);
if(end_year > start_year)
e = e + ((end_year - start_year -1) * 12);
else e--;
for(var i = s;i <= e+1; i++){
var m = new Month(s,y);
s++;
if(s > 11){
s = 0;
y++;
}
if(e == 0)
agenda_space.text("Invalid Range of Dates.")
else
agenda_space.append(m.monthDom);
}
loading(false);
}
this.hide = function(){
cache = true;
_calendar.rangeSelection.hide();
agenda_space.hide();
_calendar.navigation.show();
_calendar.calendar.show();
}
this.show = function(){
_calendar.rangeSelection.show();
agenda_space.show();
}
var copyObject = function(x){
return x.clone();
}
var eventsManager = function(){
var url = "/xhr/calendars/agenda",
sd = new Date(start_year,start_month,1),
ed = new Date(end_year,end_month+1,0);
$.ajax({
type : "get",
url : url,
data : {"agenda_start":sd.toLocaleString(),"agenda_end":ed.toLocaleString(),"page_id" : _calendar.page_id},
success : function(events){
$.each(events,function(i,e){
var ed = eventDom(e),
s = new Date(e.start),
e = new Date(e.end),
e_m = ((e.getMonth() > s.getMonth() || s.getMonth() == e.getMonth()) && s.getFullYear() == e.getFullYear() ? e.getMonth() : e.getMonth() + 12)
s_m = s.getMonth(),
s_y = s.getFullYear();
if(e.getFullYear() > s.getFullYear())
e_m = e_m + ((e.getFullYear() - s.getFullYear() -1) * 12);
for(var i = s_m; i < e_m + 1; i++){
var temp_ed = copyObject(ed);
var list = agenda_space.find("div[data-month="+s_m+"][data-year="+s_y+"] table.event_list tbody");
list.append(temp_ed);
s_m++;
if(s_m > 11){
s_m = 0;
s_y++;
}
}
if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear()){
var td = agenda_space.find("td[data-date-node="+s.getDate()+"-"+s.getMonth()+"-"+s.getFullYear()+"]");
td.addClass("has_event");
}else{
var timeDiff = Math.abs(e.getTime() - s.getTime()),
diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)),
c_m = s.getMonth(),
c_d = s.getDate(),
c_y = s.getFullYear(),
end_of_c_month = new Date(s.getFullYear(),s.getMonth()+1,0).getDate();
for(var i = 0; i <= diffDays; i++){
var td = agenda_space.find("td[data-date-node="+c_d+"-"+c_m+"-"+c_y+"]");
td.addClass("has_event");
c_d++;
if(c_d > end_of_c_month){
c_d = 1;
c_m++;
if(c_m > 11){
c_m = 0;
c_y++;
}
}
}
}
})
agenda_space.find("table.event_list tbody").each(function(){
if($(this).find("tr").length > 1)
$(this).find("td.no_events").parent().remove();
})
}
})
var eventDom = function(event){
var e_t = $(event_template),
s = new Date(event.start),
e = new Date(event.end),
dateFormat = "";
if(s.getDate() == e.getDate() && s.getMonth() == s.getMonth() && e.getFullYear() == e.getFullYear())
dateFormat = $.fullCalendar.formatDate(s, "ddd dd");
else
dateFormat = $.fullCalendar.formatDates(s, e, "ddd dd, MMM - {ddd dd, MMM}");
e_t.find("th").text(dateFormat);
e_t.find("td.event_time").text((event.allDay ? "All Day" : $.fullCalendar.formatDate(s, "hh:mm")));
e_t.find("div.event").text(event.title).css("color",event.color);
return e_t;
}
}
var loading = function(bool) {
if (bool) _calendar.loading.css("left",($(window).width()/2 - 60) + "px").show();
else _calendar.loading.hide();
}
var renderHead = function(){
var head = $(head_template);
var start_month_select = head.find("select[name=start_month]");
for(var i = 0; i < 12; i++){
var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
if(i == start_month)
option.attr("selected","selected");
start_month_select.append(option);
}
var end_month_select = head.find("select[name=end_month]");
for(var i = 0; i < 12; i++){
var option = $("<option value='"+i+"'>"+monthNames[i]+"</option>");
if(i == end_month)
option.attr("selected","selected");