247 lines
12 KiB
JavaScript
247 lines
12 KiB
JavaScript
(function ($) {
|
|
|
|
$.fn.calendar_yearview_blocks = function (options) {
|
|
|
|
// Format string
|
|
if (!String.prototype.formatString) {
|
|
String.prototype.formatString = function () {
|
|
var args = arguments;
|
|
return this.replace(/{(\d+)}/g, function (match, number) {
|
|
return typeof args[number] !== 'undefined'
|
|
? args[number]
|
|
: match
|
|
;
|
|
});
|
|
};
|
|
}
|
|
|
|
// If the number less than 10, add a zero before it
|
|
var prettyNumber = function (number) {
|
|
return number < 10 ? '0' + number.toString() : number = number.toString();
|
|
};
|
|
|
|
var getDisplayDate = function (date_obj) {
|
|
var pretty_month = prettyNumber(date_obj.getMonth() + 1);
|
|
var pretty_date = prettyNumber(date_obj.getDate());
|
|
return "{0}-{1}-{2}".formatString(date_obj.getFullYear(), pretty_month, pretty_date);
|
|
};
|
|
|
|
var start = function () {
|
|
obj_timestamp = JSON.parse(settings.data);
|
|
|
|
var wrap_chart = _this;
|
|
|
|
var end_date = new Date(settings.final_date);
|
|
end_date.setDate(end_date.getDate()+1);
|
|
var current_date = new Date();
|
|
var start_date = new Date();
|
|
start_date.setMonth(end_date.getMonth() - 12);
|
|
end_year = end_date.getFullYear()
|
|
|
|
var start_weekday = settings.start_monday === true?1:0;
|
|
for (var i = 0; i < 7; i++) {
|
|
var day = start_date.getDay();
|
|
if (day === start_weekday) {
|
|
break;
|
|
}
|
|
else {
|
|
// Loop until start_weekday
|
|
start_date.setDate(start_date.getDate() + 1);
|
|
}
|
|
}
|
|
var loop_html = "";
|
|
|
|
// One year has 52 weeks
|
|
var step = 13; // Amount of pixels to move
|
|
|
|
var month_position = [];
|
|
month_position.push({month_index: start_date.getMonth(), x: 0});
|
|
var using_month = start_date.getMonth();
|
|
for (var i = 0; i <= 52; i++) { // For each week, generate a column
|
|
var g_x = i * step;
|
|
var item_html = '<g transform="translate(' + g_x.toString() + ',0)">';
|
|
|
|
for (var j = 0; j < 7; j++) { // For each weekday, generate a row
|
|
|
|
if (start_date > end_date) {
|
|
// Break the loop when today's date is found
|
|
break;
|
|
}
|
|
var y = j * step;
|
|
|
|
var month_in_day = start_date.getMonth();
|
|
var data_date = getDisplayDate(start_date);
|
|
|
|
// Check first day in week
|
|
if (j === start_weekday && month_in_day !== using_month) {
|
|
using_month = month_in_day;
|
|
month_position.push({month_index: using_month, x: g_x});
|
|
}
|
|
|
|
// Put a box around today's date
|
|
if (settings.stylize_today) {
|
|
var match_today = current_date.getTime() === start_date.getTime() ? '" style="stroke:black;stroke-width:2;opacity:0.5"' : '';
|
|
} else {
|
|
var match_today = "";
|
|
}
|
|
|
|
var items = [];
|
|
var legend = '', items_str = '';
|
|
if (obj_timestamp[data_date]) {
|
|
if (obj_timestamp[data_date].items) {
|
|
items = obj_timestamp[data_date].items;
|
|
items_str = items.join(", ")
|
|
items_str = items_str.replaceAll('&', '&');
|
|
items_str = items_str.replaceAll('"', '"');
|
|
}
|
|
if (obj_timestamp[data_date].legend) {
|
|
legend = obj_timestamp[data_date].legend;
|
|
legend = legend.replaceAll('&', '&');
|
|
legend = legend.replaceAll('"', '"');
|
|
}
|
|
}
|
|
|
|
var item_name = items[0]?items[0]:false;
|
|
var color = settings.colors[item_name]?settings.colors[item_name]:settings.colors['default'];
|
|
|
|
// Fill a square for the 1st item
|
|
item_html += '<rect class="day" width="11" height="11" y="' + y + '" fill="' + color + match_today + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
if (items.length === 2) { // Fill a trangle for the 2nd
|
|
var item_name_1 = items[1]?items[1]:false;
|
|
var color_1 = settings.colors[item_name_1]?settings.colors[item_name_1]:settings.colors['default'];
|
|
item_html += '<polygon points="' + 0 + ',' + (y+11) + ' ' + 0 + ',' + y + ' ' + 11 + ',' + y + '" fill="' + color_1 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
} else if (items.length === 3) { // Fill 2 rectangles for 2nd and 3rd
|
|
var item_name_1 = items[1]?items[1]:false;
|
|
var color_1 = settings.colors[item_name_1]?settings.colors[item_name_1]:settings.colors['default'];
|
|
var item_name_2 = items[2]?items[2]:false;
|
|
var color_2 = settings.colors[item_name_2]?settings.colors[item_name_2]:settings.colors['default'];
|
|
item_html += '<polygon points="' + 0 + ',' + (y+8) + ' ' + 0 + ',' + y + ' ' + 11 + ',' + y + ' ' + 11 + ',' + (y+8) + '" fill="' + color_1 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
item_html += '<polygon points="' + 0 + ',' + (y+4) + ' ' + 0 + ',' + y + ' ' + 11 + ',' + y + ' ' + 11 + ',' + (y+4) + '" fill="' + color_2 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
} else if (items.length === 4) { // Fill 3 cubes for 2nd, 3rd and 4th
|
|
var item_name_1 = items[1]?items[1]:false;
|
|
var color_1 = settings.colors[item_name_1]?settings.colors[item_name_1]:settings.colors['default'];
|
|
var item_name_2 = items[2]?items[2]:false;
|
|
var color_2 = settings.colors[item_name_2]?settings.colors[item_name_2]:settings.colors['default'];
|
|
var item_name_3 = items[3]?items[3]:false;
|
|
var color_3 = settings.colors[item_name_3]?settings.colors[item_name_3]:settings.colors['default'];
|
|
item_html += '<polygon points="' + 0 + ',' + (y+11) + ' ' + 0 + ',' + (y+6) + ' ' + 6 + ',' + (y+6) + ' ' + 6 + ',' + (y+11) + '" fill="' + color_1 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
item_html += '<polygon points="' + 0 + ',' + (y+6) + ' ' + 0 + ',' + y + ' ' + 6 + ',' + y + ' ' + 6 + ',' + (y+6) + '" fill="' + color_2 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
item_html += '<polygon points="' + 6 + ',' + (y+6) + ' ' + 6 + ',' + y + ' ' + 11 + ',' + y + ' ' + 11 + ',' + (y+6) + '" fill="' + color_3 + '" data-items="' + items_str + '" data-legend="' + legend + '" data-date="' + data_date + '"/>';
|
|
}
|
|
|
|
// Move on to the next day
|
|
start_date.setDate(start_date.getDate() + 1);
|
|
|
|
}
|
|
|
|
item_html += "</g>";
|
|
|
|
loop_html += item_html;
|
|
|
|
}
|
|
|
|
// Trick
|
|
if (month_position[1].x - month_position[0].x < 40) {
|
|
// Fix ugly graph by removing the first item
|
|
month_position.shift(0);
|
|
}
|
|
|
|
// Add labels for Months
|
|
for (var i = 0; i < month_position.length; i++) {
|
|
var item = month_position[i];
|
|
var month_name = item.month_index ? settings.month_names[item.month_index] : end_year;
|
|
loop_html += '<text x="' + item.x + '" y="-5" class="month">' + month_name + '</text>';
|
|
}
|
|
|
|
// Add labels for Weekdays
|
|
if (settings.start_monday === true) {
|
|
loop_html += '<text text-anchor="middle" class="wday" dx="-12" dy="11">{0}</text>'.formatString(settings.day_names[0]) +
|
|
'<text text-anchor="middle" class="wday" dx="-12" dy="36">{0}</text>'.formatString(settings.day_names[1]) +
|
|
'<text text-anchor="middle" class="wday" dx="-12" dy="61">{0}</text>'.formatString(settings.day_names[2]) +
|
|
'<text text-anchor="middle" class="wday" dx="-12" dy="86">{0}</text>'.formatString(settings.day_names[3]);
|
|
} else {
|
|
loop_html += '<text text-anchor="middle" class="wday" dx="-10" dy="22">{0}</text>'.formatString(settings.day_names[0]) +
|
|
'<text text-anchor="middle" class="wday" dx="-10" dy="48">{0}</text>'.formatString(settings.day_names[1]) +
|
|
'<text text-anchor="middle" class="wday" dx="-10" dy="74">{0}</text>'.formatString(settings.day_names[2]);
|
|
}
|
|
|
|
// Fixed size with width= 721 and height = 110
|
|
var wire_html =
|
|
'<svg width="700" height="100">' +
|
|
'<g transform="translate(0, 20)">' +
|
|
loop_html +
|
|
'</g>' + '"Your browser does not support inline SVG."' +
|
|
'</svg>';
|
|
|
|
wrap_chart.html(wire_html);
|
|
|
|
_this.find('rect, polygon').on("mouseenter", mouseEnter);
|
|
_this.find('rect, polygon').on("mouseleave", mouseLeave);
|
|
_this.find('rect, polygon').on("click", mouseClick);
|
|
appendTooltip();
|
|
|
|
};
|
|
|
|
var mouseLeave = function (evt) {
|
|
$('.svg-tip').hide();
|
|
};
|
|
|
|
var mouseClick = function (evt) {
|
|
var items = $(evt.target).attr('data-items');
|
|
var date = $(evt.target).attr('data-date');
|
|
$("#moreinfo").text("On {0}, following items are seen: {1}".formatString(date, items))
|
|
};
|
|
|
|
// Handle mouseEnter event when entering into rect element
|
|
var mouseEnter = function (evt) {
|
|
|
|
var target_offset = $(evt.target).offset();
|
|
var items = $(evt.target).attr('data-items');
|
|
var legend = $(evt.target).attr('data-legend');
|
|
var date = $(evt.target).attr('data-date');
|
|
|
|
var text = settings.tooltip_style === 'default' ? "{0}: <br />{1}".formatString(date, legend ? legend : items) : (legend ? legend : items);
|
|
|
|
// Depending on settings, only show a tooltip when there's something to be shown
|
|
if (items.length >= 1 || settings.always_show_tooltip === true) {
|
|
var svg_tip = $('.svg-tip').show();
|
|
svg_tip.html(text);
|
|
var svg_width = Math.round(svg_tip.width() / 2 + 5);
|
|
var svg_height = svg_tip.height() * 2 + 10;
|
|
|
|
svg_tip.css({top: target_offset.top - svg_height - 5});
|
|
svg_tip.css({left: target_offset.left - svg_width});
|
|
}
|
|
|
|
};
|
|
|
|
// Append tooltip to display when the mouse enters the rect element
|
|
// Default is display:none
|
|
var appendTooltip = function () {
|
|
if ($('.svg-tip').length === 0) {
|
|
$('body').append('<div class="svg-tip svg-tip-one-line" style="display:none" ></div>');
|
|
}
|
|
};
|
|
|
|
// Default settings which can be overridden by the user
|
|
var settings = $.extend({
|
|
colors: {
|
|
'default': '#eeeeee'
|
|
},
|
|
month_names: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
day_names: ['M', 'W', 'F', 'S'],
|
|
start_monday: true,
|
|
always_show_tooltip: false,
|
|
stylize_today: false,
|
|
final_date: new Date().toISOString().slice(0, 10),
|
|
tooltip_style: 'default', // or 'custom'
|
|
data: []
|
|
}, options);
|
|
|
|
var _this = $(this);
|
|
|
|
start();
|
|
|
|
};
|
|
|
|
}($));
|