513 lines
17 KiB
HTML
513 lines
17 KiB
HTML
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
|
{% load origin %}{% origin %}
|
|
{% load static %}
|
|
<html> <head>
|
|
<script type="text/javascript">
|
|
|
|
var all_items = {{ items|safe }};
|
|
|
|
/* Saturday events need to be moved to the day -1 */
|
|
/* Also, process clock times to "minutes past midnight" */
|
|
all_items.forEach(function(item) {
|
|
if (item.day == 6) { item.day = -1; }
|
|
item.start_time = parseInt(item.time.substr(0,2),10) * 60 +
|
|
parseInt(item.time.substr(2,2),10);
|
|
item.end_time = item.start_time + (item.duration / 60)
|
|
});
|
|
|
|
var color = {
|
|
'app': { fg: "#008", bg: "#eef"},
|
|
'art': { fg: "#808", bg: "#fef"},
|
|
'gen': { fg: "#080", bg: "#efe"},
|
|
'int': { fg: "#088", bg: "#eff"},
|
|
'ops': { fg: "#800", bg: "#fee"},
|
|
'rai': { fg: "#808", bg: "#fef"},
|
|
'rtg': { fg: "#880", bg: "#ffe"},
|
|
'sec': { fg: "#488", bg: "#dff"},
|
|
'tsv': { fg: "#484", bg: "#dfd"},
|
|
'irtf': { fg: "#448", bg: "#ddf"},
|
|
'break': { fg: "#000", bg: "#fff"},
|
|
}
|
|
|
|
var day = [
|
|
'Saturday',
|
|
'Sunday',
|
|
'Monday',
|
|
'Tuesday',
|
|
'Wednesday',
|
|
'Thursday',
|
|
'Friday'
|
|
];
|
|
|
|
var padding = 2;
|
|
var border = 1;
|
|
|
|
//===========================================================================
|
|
function compute_swimlanes(items) {
|
|
var start_map = items.map(function(el, i) {
|
|
return { day: parseInt(el.day,10), start_time: el.start_time, index: i };
|
|
});
|
|
|
|
start_map.sort(function(a,b) {
|
|
if (a.day != b.day) { return(a.day - b.day); }
|
|
return (a.start_time - b.start_time);
|
|
});
|
|
|
|
var end_map = items.map(function(el, i) {
|
|
return { day: parseInt(el.day,10), end_time: el.end_time, index: i };
|
|
});
|
|
|
|
end_map.sort(function(a,b) {
|
|
if (a.day != b.day) { return(a.day - b.day); }
|
|
return (a.end_time - b.end_time);
|
|
});
|
|
|
|
var si = 0; // start index
|
|
var ei = 0; // end index
|
|
var overlap = 0;
|
|
var max_lanes = 0;
|
|
var next_lane = [];
|
|
|
|
var start_overlap = si;
|
|
while (si < items.length) {
|
|
var start_day_change = false;
|
|
while ( !start_day_change
|
|
&& si < items.length
|
|
&& start_map[si].start_time < end_map[ei].end_time ) {
|
|
overlap++;
|
|
if (next_lane.length > 0) {
|
|
items[start_map[si].index].lane = next_lane.shift();
|
|
} else {
|
|
items[start_map[si].index].lane = max_lanes;
|
|
max_lanes++;
|
|
}
|
|
start_day_change = ( si+1 == items.length
|
|
|| start_map[si].day != start_map[si+1].day );
|
|
si++;
|
|
}
|
|
var end_day_change = false;
|
|
while ( ei < items.length
|
|
&& !end_day_change
|
|
&& ( start_day_change
|
|
|| si == items.length
|
|
|| start_map[si].start_time >= end_map[ei].end_time ) ) {
|
|
next_lane.push(items[end_map[ei].index].lane);
|
|
overlap--;
|
|
end_day_change = ( ei+1 == items.length
|
|
|| end_map[ei].day != end_map[ei+1].day );
|
|
ei++;
|
|
}
|
|
if (overlap == 0)
|
|
{
|
|
for (var i=start_overlap; i<si; i++) {
|
|
items[start_map[i].index].lanes = max_lanes;
|
|
}
|
|
max_lanes = 0;
|
|
next_lane=[];
|
|
start_overlap = si;
|
|
}
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function is_visible(include) {
|
|
return function (item) {
|
|
// "-wgname" will remove a working group from the output.
|
|
// "~Type" will add that type to the output.
|
|
// "-~Type" will remove that type from the output
|
|
// "@bof" will include all BOFs
|
|
// Current types are:
|
|
// Session, Other, Break, Plenary
|
|
|
|
if ("group" in item) {
|
|
if (include[(item.group).toLowerCase()]) { return true; }
|
|
if (include["-"+(item.group).toLowerCase()]) { return false; }
|
|
}
|
|
if ("state" in item) {
|
|
if (include["@"+(item.state).toLowerCase()]) { return true; }
|
|
}
|
|
if (include["~"+(item.type).toLowerCase()]) { return true; }
|
|
if (include["-~"+(item.type).toLowerCase()]) { return false; }
|
|
if ("area" in item) {
|
|
if (include[(item.area).toLowerCase()]) { return true; }
|
|
}
|
|
if (item.type === "Plenary") { return true; }
|
|
if (item.type === "Other") { return true; }
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function draw_calendar() {
|
|
var width = document.body.clientWidth;
|
|
var height = document.body.clientHeight;
|
|
|
|
var include = {};
|
|
window.location.hash.replace("#",'').split(',').forEach(function(key){
|
|
include[(key + "").toLowerCase()] = true;
|
|
});
|
|
|
|
var visible_items = all_items.filter(is_visible(include));
|
|
|
|
var start_day = visible_items[0].day;
|
|
var end_day = start_day;
|
|
var day_start = visible_items[0].start_time;
|
|
var day_end = 0;
|
|
|
|
compute_swimlanes(visible_items);
|
|
|
|
/* Find our boundaries */
|
|
visible_items.forEach(function(item){
|
|
day_start = Math.min(day_start, item.start_time);
|
|
day_end = Math.max(day_end, item.end_time);
|
|
start_day = Math.min(start_day, item.day)
|
|
end_day = Math.max(start_day, item.day)
|
|
});
|
|
|
|
var header_height = height * 0.05 ;
|
|
|
|
var num_days = end_day - start_day + 1;
|
|
var num_minutes = day_end - day_start;
|
|
var day_width = width / num_days;
|
|
var minute_height = (height - header_height)/num_minutes;
|
|
|
|
while (document.body.firstChild) {
|
|
document.body.removeChild(document.body.firstChild);
|
|
}
|
|
|
|
var j = start_day;
|
|
for (var i = 0; i < num_days; i++) {
|
|
//-----------------------------------------------------------------
|
|
// Draw weekday name
|
|
//-----------------------------------------------------------------
|
|
var e = document.createElement("div");
|
|
|
|
e.style.border="solid";
|
|
e.style.borderWidth=border;
|
|
|
|
e.style.background="#2647a0";
|
|
e.style.color="#fff";
|
|
e.style.borderColor="#000 #fff";
|
|
e.style.borderColor="#2647a0 #2647a0 #000 #2647a0";
|
|
|
|
e.style.display="block";
|
|
e.style.overflow="hidden";
|
|
e.style.position="absolute";
|
|
|
|
e.style.top=0;
|
|
e.style.left = i*day_width;
|
|
e.style.width=day_width - 2 * (padding + border);
|
|
e.style.height=header_height;
|
|
|
|
e.style.margin=0;
|
|
e.style.padding=padding;
|
|
e.style.fontFamily="sans-serif";
|
|
e.style.fontSize=header_height * 0.6;
|
|
|
|
e.style.textAlign="center";
|
|
|
|
var div = document.createElement("div");
|
|
div.appendChild(document.createTextNode(day[j+1]));
|
|
j++;
|
|
e.appendChild(div);
|
|
document.body.appendChild(e);
|
|
|
|
//-----------------------------------------------------------------
|
|
// Draw weekday column border
|
|
//-----------------------------------------------------------------
|
|
e = document.createElement("div");
|
|
|
|
e.style.border="solid";
|
|
e.style.borderWidth=border;
|
|
|
|
e.style.background="#fff";
|
|
e.style.color="#000";
|
|
e.style.borderColor="#fff #000";
|
|
|
|
e.style.display="block";
|
|
e.style.overflow="hidden";
|
|
e.style.position="absolute";
|
|
|
|
e.style.top=header_height;
|
|
e.style.left=i*day_width;
|
|
e.style.width=day_width - 2 * (padding + border);
|
|
e.style.height=height -
|
|
2 * (padding + border) - header_height;
|
|
|
|
e.style.margin=0;
|
|
e.style.padding=padding;
|
|
|
|
document.body.appendChild(e);
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
// Draw a block for each meeting
|
|
//-----------------------------------------------------------------
|
|
visible_items.forEach(function(item) {
|
|
var sess_width = day_width / item.lanes;
|
|
var sess_height = ((item.end_time - item.start_time) * minute_height)
|
|
- 2 * (padding + border);
|
|
var day_left = ((item.day - start_day) * day_width);
|
|
var sess_left = day_left + sess_width * item.lane;
|
|
var sess_top = ((item.start_time - day_start) * minute_height) + header_height;
|
|
|
|
sess_width = sess_width - 2 * (padding + border);
|
|
|
|
var e = document.createElement("div");
|
|
e.style.border = "solid";
|
|
e.style.borderWidth = border;
|
|
|
|
if (item.area && color[item.area]) {
|
|
e.style.background=color[item.area].bg;
|
|
e.style.color=color[item.area].fg;
|
|
e.style.borderColor=color[item.area].fg;
|
|
} else {
|
|
if (item.area) {
|
|
console.log("No color for " + item.area + ": using default");
|
|
}
|
|
e.style.background="#e0e0e0";
|
|
e.style.color="#000000";
|
|
e.style.borderColor="#000000";
|
|
}
|
|
|
|
e.style.display="block";
|
|
e.style.overflow="hidden";
|
|
e.style.position="absolute";
|
|
e.style.top=sess_top;
|
|
e.style.left=sess_left;
|
|
e.style.width=sess_width;
|
|
e.style.height=sess_height;
|
|
e.style.margin=0;
|
|
e.style.padding=padding;
|
|
e.style.fontFamily="sans-serif";
|
|
e.style.fontSize="8pt";
|
|
e.item=item;
|
|
|
|
e.onmouseenter = function(){resize(e,sess_top,day_left,
|
|
day_width-2*(padding+border),
|
|
sess_height, true)};
|
|
|
|
e.onmouseleave = function(){resize(e,sess_top,sess_left,sess_width,sess_height,false)};
|
|
|
|
if (item.agenda) {
|
|
e.onclick=function(){maximize(e)};
|
|
e.style.cursor="pointer";
|
|
}
|
|
|
|
var div = document.createElement("div");
|
|
div.appendChild(document.createTextNode(item.time));
|
|
div.appendChild(document.createElement("br"));
|
|
|
|
var label = item.name;
|
|
if (label.length === 0) {
|
|
label = "Free Slot";
|
|
}
|
|
if (item.group && color[item.area]) {
|
|
label = label + " (" + item.group + ")";
|
|
}
|
|
|
|
var bold = document.createElement("span");
|
|
bold.appendChild(document.createTextNode(label));
|
|
bold.style.fontWeight="bold";
|
|
div.appendChild(bold);
|
|
|
|
if (item.room) {
|
|
div.appendChild(document.createElement("br"));
|
|
var italics = document.createElement("span");
|
|
italics.appendChild(document.createTextNode(item.room));
|
|
italics.style.fontStyle="oblique";
|
|
div.appendChild(italics);
|
|
}
|
|
|
|
e.appendChild(div);
|
|
|
|
document.body.appendChild(e);
|
|
});
|
|
}
|
|
|
|
//===========================================================================
|
|
// Note: if "to_fit" is true and the text won't fit in the dimensions
|
|
// provided, then the height parameter is ignored, and the item is resized to
|
|
// be tall enough to contain the entire contents
|
|
|
|
var animation_counter = 0;
|
|
function resize(div, top, left, width, height, to_fit) {
|
|
var from_top = (div.style.top.replace("px",""));
|
|
var from_left = (div.style.left.replace("px",""));
|
|
var from_width = (div.style.width.replace("px",""));
|
|
var from_height = (div.style.height.replace("px",""));
|
|
|
|
// If we're fitting the height to the content, and there is overflow,
|
|
// calculate the new (larger) height
|
|
if (to_fit) {
|
|
div.style.removeProperty("height");
|
|
div.style.width = width;
|
|
var clientHeight = div.clientHeight;
|
|
div.style.height = from_height;
|
|
div.style.width = from_width;
|
|
if (clientHeight > height) {
|
|
height = clientHeight;
|
|
}
|
|
}
|
|
|
|
var animationId = "animation-" + (animation_counter++);
|
|
|
|
// Move the element to the front
|
|
div.style.zIndex = animation_counter;
|
|
|
|
var style = document.createElement('style');
|
|
style.textContent = "@keyframes " + animationId + " {" +
|
|
" from {" +
|
|
" top: " + from_top + ";" +
|
|
" left: " + from_left + ";" +
|
|
" width: " + from_width + ";" +
|
|
" height: " + from_height + ";" +
|
|
" }" +
|
|
" to {" +
|
|
" top: " + top + ";" +
|
|
" left: " + left + ";" +
|
|
" width: " + width + ";" +
|
|
" height: " + height + ";" +
|
|
" }" +
|
|
"}";
|
|
document.head.appendChild(style);
|
|
|
|
var callback = function() {
|
|
div.removeEventListener('animationend',callback);
|
|
document.head.removeChild(style);
|
|
|
|
div.style.top = top;
|
|
div.style.left = left;
|
|
div.style.width = width;
|
|
div.style.height = height;
|
|
|
|
if (div.callback) {
|
|
div.callback();
|
|
div.callback = undefined;
|
|
}
|
|
};
|
|
|
|
div.addEventListener('animationend', callback, false);
|
|
|
|
div.style.animationName = animationId;
|
|
div.style.animationDuration = "0.25s";
|
|
div.style.animationIterationCount = "1";
|
|
div.style.animationFillMode="forwards";
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function finish_maximize(e) {
|
|
if (!e.item.agenda) {
|
|
console.log("Element has no agenda: " + JSON.stringify(e.item));
|
|
return;
|
|
}
|
|
|
|
e.insertBefore(document.createElement("br"),e.firstChild);
|
|
|
|
var img = document.createElement("img");
|
|
img.src = "{% static 'ietf/images/agenda-weekview/close.png' %}";
|
|
img.style.cssFloat="right";
|
|
img.onclick = function() {minimize(e);};
|
|
img.style.cursor="pointer";
|
|
e.insertBefore(img,e.firstChild);
|
|
|
|
var h = document.createElement("span");
|
|
h.appendChild(document.createTextNode(e.item.dayname));
|
|
h.style.fontWeight="bold";
|
|
e.insertBefore(h,e.firstChild);
|
|
e.style.fontSize="10pt";
|
|
|
|
var tmp = e.style.height;
|
|
e.style.removeProperty("height");
|
|
var used_height = e.clientHeight;
|
|
e.style.height = tmp;
|
|
|
|
var frame = document.createElement("iframe");
|
|
frame.setAttribute("src",e.item.agenda);
|
|
|
|
frame.style.position = "absolute";
|
|
frame.style.left = 8;
|
|
frame.style.width = e.clientWidth - 16 - 2 * (padding + border);
|
|
frame.style.top = used_height + 8;
|
|
frame.style.height = e.clientHeight - used_height - 16 - 2*(padding+border);
|
|
|
|
frame.style.background = "#fff";
|
|
frame.style.overflow="auto";
|
|
frame.id="agenda";
|
|
|
|
frame.style.border = e.style.border;
|
|
frame.style.borderWidth = border;
|
|
frame.style.padding = padding;
|
|
frame.style.borderColor = e.style.borderColor;
|
|
|
|
e.appendChild(frame);
|
|
|
|
e.keyHandler = function(event) {
|
|
console.log(event.code);
|
|
if(event.code === "Escape") {
|
|
minimize(e);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('keydown', e.keyHandler, false);
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function finish_minimize(e) {
|
|
e.onmouseenter = e.oldmouseenter;
|
|
e.onmouseleave = e.oldmouseleave;
|
|
e.oldmouseenter = undefined;
|
|
e.oldmouseleave = undefined;
|
|
e.style.cursor="pointer";
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function maximize(e) {
|
|
if (e.onmouseenter)
|
|
{
|
|
e.oldmouseenter = e.onmouseenter;
|
|
e.oldmouseleave = e.onmouseleave;
|
|
e.onmouseenter = undefined;
|
|
e.onmouseleave = undefined;
|
|
e.style.cursor="auto";
|
|
e.callback = function(){finish_maximize(e);}
|
|
resize(e,0,0,
|
|
document.body.clientWidth-2*(padding + border),
|
|
document.body.clientHeight-2*(padding + border), false);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
function minimize(e) {
|
|
var agenda = document.getElementById("agenda");
|
|
if (agenda) {
|
|
e.removeChild(agenda);
|
|
}
|
|
document.removeEventListener('keydown', e.keyHandler, false);
|
|
e.callback = function(){finish_minimize(e);};
|
|
e.oldmouseleave();
|
|
e.removeChild(e.firstChild);
|
|
e.removeChild(e.firstChild);
|
|
e.removeChild(e.firstChild);
|
|
e.style.fontSize="8pt";
|
|
}
|
|
|
|
//===========================================================================
|
|
// Set up events for drawing the calendar
|
|
window.addEventListener("resize", draw_calendar, false);
|
|
window.addEventListener("load", draw_calendar, false);
|
|
window.addEventListener("hashchange", draw_calendar, false);
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="cal"><span>Error loading calendar</span></div>
|
|
</body></html>
|