<!--
parameter
required:
id: [integer] room id, see in admin panel
optional:
lang:[en,de] set the language
mode:[1,2,3,4] sets the displaying
1: Calendar & Room
2: only Calendar
3: only Room
4: Calendar & Room alternately
daystoshow:[1,2,3,4,5,6,7] sets how many days the calendar shows
scale:[10-90] scales the calendar and Roomplan in mode 1
switchtime:[1-120] sets the time between switchen in mode 4 (in seconds)
calupdate: Time the calender querys for updates,in minutes.
roomupdate: Time the PCs in the room gets updated,in seconds.
rotation:[0-3] rotation of the roomplan
vertical:[true] only mode 1, sets the calendar above the roomplan
configupdate: Time interval the config gets updated (in minutes)
scaledaysauto: [true] if true it finds automaticly the daystoshow parameter depending on display size
-->
<!DOCTYPE html>
<html lang="de">
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8">
<head>
<title>DoorSign</title>
<script type='text/javascript' src='../../../script/jquery.js'></script>
<script type='text/javascript' src='../../js_jqueryui/clientscript.js'></script>
<link rel='stylesheet' type='text/css' href='../../js_jqueryui/style.css'/>
<link rel='stylesheet' type='text/css' href='jquery-week-calendar/jquery.weekcalendar.css'/>
<script type='text/javascript' src="jquery-week-calendar/jquery.weekcalendar.js"></script>
<style type='text/css'>
body {
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
margin: 0;
width: 100%;
height: 100%;
float: left;
box-sizing: border-box;
background-color: #cacaca;
overflow: hidden;
position: absolute;
display: table;
}
.row {
background-color: #404040;
box-shadow: 0 0.1875rem 0.375rem rgba(0, 0, 0, 0.25);
margin-bottom: 4px;
width: 100%;
}
.header {
display: table;
color: white;
padding: 0;
height: 8vw;
}
.progressbar {
width: 0px;
height: 2px;
position: absolute;
background-color: red;
bottom: 2px;
z-index: 1;
}
.font {
display: table-cell;
vertical-align: middle;
font-size: 3vw;
font-weight: bold
}
.courseText {
text-align: center;
}
.row::after {
content: "";
clear: both;
display: block;
}
[class*="col-"] {
float: left;;
padding: 0;
box-sizing: border-box;
}
.col-1 {
width: 33%;
}
.col-2 {
width: 33%;
}
.roomLayoutDesign {
position: relative;
float: left;
boxSizing: border-box;
}
.roompadding {
float: left;
position: relative;
}
.room {
position: relative;
background-color: white;
width: 100%;
height: 100%;
overflow: hidden;
border-width: 1px;
border-color: darkgrey;
border-style: solid;
}
.calendar {
float: left;
padding: 0;
dboxSizing: border-box;
background: linear-gradient(#cccccc, white);
}
.free-busy-busy {
background: grey;
}
.ui-widget-content {
color: white;
}
.wc-header {
background-color: #404040;
font-weight: bold;
}
.ui-state-default {
text-shadow: none;
}
.square {
display: table;
float: right;
padding: 0;
width: 8vw;
height: 8vw;
}
.FreeSeatsFont {
display: table-cell;
vertical-align: middle;
font-size: 6vw;
color: white;
top: 0;
margin: 0 auto;
position: relative;
text-align: center;
font-weight: bold;
overflow: visible;
}
.PCImgDiv{
position: absolute;
left: 0;
bottom: 0;
display: inline-block;
}
.OverlayDiv{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
display: table;
}
.pcImg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height:100%;
}
.overlay{
position: relative;
width: 50%;
height: 50%;
opacity: 0.5;
float:left;
z-index: 5;
}
.overlay-rollstuhl {
width: 25%;
height: 50%;
background-color: white;
opacity: 0.5;
float:left;
}
.wc-scrollable-grid {
}
.ui-widget-content .ui-state-active {
font-weight: bold;
color: black;
}
.wc-container {
font-weight: bold;
}
.wc-today {
background-color: white;
}
.wc-time-header-cell {
background-color: #eeeeee;
border: none;
}
.ui-corner-all {
moz-border-radius-bottomright: 0;
webkit-border-bottom-right-radius: 0;
-khtml-border-bottom-right-radius: 0;
border-bottom-right-radius: 0;
moz-border-radius-topright: 0;
webkit-border-top-right-radius: 0;
-khtml-border-top-right-radius: 0;
border-top-right-radius: 0;
moz-border-radius-bottomleft: 0;
webkit-border-bottom-left-radius: 0;
-khtml-border-bottom-left-radius: 0;
border-bottom-left-radius: 0;
moz-border-radius-topleft: 0;
webkit-border-left-right-radius: 0;
-khtml-border-left-right-radius: 0;
border-top-left-radius: 0;
}
.wc-scrollable-grid .wc-day-column-first {
border-style: solid;
}
[class*="wc-day-"] {
border-color: grey;
}
</style>
<script type='text/javascript'>
var rooms = {};
var lastSwitchTime;
var roomsToshow = 0;
var roomIds;
//Todo change these
var date;
var supportSvg = typeof SVGRect != "undefined";
var calendarQueryUrl;
var translation = {
"en": {
"room": "Room",
"closed": "Closed",
"free": "Free",
"shortDays": ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
"longDays": ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
"to": "to"
},
"de": {
"room": "Raum",
"closed": "Geschlossen",
"free": "Frei",
"shortDays": ["Son", "Mon", "Die", "Mit", "Don", "Frei", "Sam"],
"longDays": ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitrag", "Samstag"],
"to": "bis"
},
"pt": {
"room": "Quarto",
"closed": "Fechado",
"free": "Livre",
"shortDays": ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Se', 'Sáb'],
"longDays": ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira',
'Sexta-feira', 'Sábado'],
"to": "para"
}
};
$(document).ready(function () {
if (!getId()) {
return;
}
});
// Downloads the config of a room
function getConfig(id, room) {
$.ajax({
url: "../../../api.php?do=locationinfo&action=config&id=" + id,
dataType: 'json',
cache: false,
timeout: 30000,
success: function (result) {
if (room == null) {
if (result.room == null) {
// Todo Error Handling: wrong id?
return;
}
var time = new Date(result.time);
if (isNaN(time.getTime())) {
time = new Date();
}
SetUpDate(time);
delete result.time;
room = addRoom(id, result.room, result);
roomsToshow++;
if (roomsToshow == roomIds.length) {
initRooms();
}
} else {
delete result.time;
if (JSON.stringify(rooms[id].config) != JSON.stringify(result)) {
// reload Page if someone changed config
location.reload(true);
}
}
// check for config changes from time to time
setTimeout(function () {
getConfig(id, room);
}, room.config.configupdate);
}, error: function () {
//Todo Error handling:
}
})
}
// gets the Parameter IDs from the Urls
function getId() {
roomIds = getUrlParameter("id");
if (roomIds == null) {
var text = "<h1>Error: No Room Id's given in parameter </h1>";
$("body").append(text);
return false;
}
roomIds = roomIds.split(',');
if (roomIds.length > 4) {
roomIds.length = 4;
}
for (var i = 0; i < roomIds.length; i++) {
getConfig(roomIds[i], null);
}
}
// gets Additional Parameters from the URL, and from the
// downloaded json.
// also makes sure parameters are in a given range
function getParamerter(room) {
var lang;
lang = room.config.lang;
if (room.config != null) {
room.config.switchtime = room.config.switchtime * 1000;
room.config.calupdate = room.config.calupdate * 60 * 1000;
room.config.roomupdate = room.config.roomupdate * 1000;
room.config.configupdate = room.config.configupdate * 60 * 1000;
}
if (getUrlParameter("mode") != null) {
room.config.mode = parseInt(getUrlParameter("mode"));
}
if (getUrlParameter("calupdate") != null) {
room.config.calupdate = (parseInt(getUrlParameter("calupdate")) * 60 * 1000);
}
if (getUrlParameter("roomupdate") != null) {
room.config.roomupdate = (parseInt(getUrlParameter("roomupdate")) * 1000);
}
if (getUrlParameter("daystoshow") != null) {
room.config.daystoshow = parseInt(getUrlParameter("daystoshow"));
}
if (getUrlParameter("scaledaysauto") == "true") {
room.config.scaledaysauto = true;
}
if (getUrlParameter("vertical") == "true") {
room.config.vertical = true;
}
if (getUrlParameter("einkmode") == "true") {
room.config.einkmode = true;
}
if (getUrlParameter("scale") != null) {
room.config.scale = parseInt(getUrlParameter("scale"));
}
if (getUrlParameter("rotation") != null) {
room.config.rotation = parseInt(getUrlParameter("rotation"));
}
if (getUrlParameter("switchtime") != null) {
room.config.switchtime = (parseInt(getUrlParameter("switchtime")) * 1000);
}
if (getUrlParameter("configupdate") != null) {
room.config.configupdate = (parseInt(getUrlParameter("configupdate")) * 60 * 1000);
}
// parameter validation
if (room.config.switchtime == null || isNaN(room.config.switchtime) || room.config.switchtime > 120
|| room.config.switchtime < 1) {
room.config.switchtime = 5;
}
if (room.config.scale == null || isNaN(room.config.scale) || room.config.scale > 90 || room.config.scale < 10) {
room.config.scale = 50;
}
if (room.config.vertical == null) {
room.config.vertical = false;
}
if (room.config.daystoshow == null || isNaN(room.config.daystoshow) || room.config.daystoshow > 7
|| room.config.daystoshow < 1) {
room.config.daystoshow = 7;
}
if (room.config.roomupdate == null || isNaN(room.config.roomupdate) || room.config.roomupdate < 1000) {
room.config.roomupdate = 20 * 1000;
}
if (room.config.configupdate == null || isNaN(room.config.configupdate) || (room.config.configupdate < 1)) {
room.config.configupdate = 30 * 60 * 1000;
}
if (room.config.calupdate == null || isNaN(room.config.calupdate) || room.config.calupdate < 60 * 1000) {
room.config.calupdate = 30 * 60 * 1000;
}
if (room.config.mode == null || isNaN(room.config.mode) || room.config.mode > 4 || room.config.mode < 1) {
room.config.mode = 1;
}
if (room.config.rotation == null || isNaN(room.config.rotation) || room.config.rotation < 0
|| room.config.rotation > 4) {
room.config.rotation = 0;
}
if (getUrlParameter("lang") != null && getUrlParameter("lang") in translation) {
room.config.lang = getUrlParameter("lang");
}
$('html').attr('lang', lang);
}
// generates the Room divs and calls the needed functions depending on the rooms mode
function initRooms() {
var width = "100%";
var height = "100%";
if (roomsToshow == 2 || roomsToshow == 4) {
width = "50%";
}
if (roomsToshow == 3) {
width = "33%";
}
if (roomsToshow == 4) {
height = "50%";
}
var i = 0;
for (var t = 0; t < roomIds.length; t++) {
var property = roomIds[t];
var text = "<div class='roompadding' id ='roompadding_" + rooms[property].id + "'></div>";
$("body").append(text);
var obj = document.getElementById("roompadding_" + rooms[property].id);
obj.style.height = height;
obj.style.width = width;
text = "<div class='room' id ='room_" + rooms[property].id + "'></div>";
$("#roompadding_" + rooms[property].id).append(text);
text = "<div id='header_" + rooms[property].id + "' class='row'>" +
"<div class='header col-2'>" +
"<div class='font' id='roomHeader_" + rooms[property].id + "'></div>" +
"</div>" +
"<div class='col-1 courseText header'>" +
"<div class='font' id='courseHeading_" + rooms[property].id + "'></div>" +
"</div>" +
"<div class='square .col-2' id='square_" + rooms[property].id + "'>" +
"<div class='FreeSeatsFont' id='freeSeatsHeader_" + rooms[property].id + "'></div>" +
"</div>" +
"</div>";
$("#room_" + rooms[property].id).append(text);
if (rooms[property].name != null) {
$("#roomHeader_" + rooms[property].id).text(rooms[property].name);
}
if (roomsToshow == 2) {
document.getElementById("square_" + rooms[property].id).style.width = "6vw";
document.getElementById("square_" + rooms[property].id).style.height = "6vw";
document.getElementById("roomHeader_" + rooms[property].id).style.fontSize = "1.8vw";
document.getElementById("freeSeatsHeader_" + rooms[property].id).style.fontSize = "4.5vw";
document.getElementById("courseHeading_" + rooms[property].id).style.fontSize = "1.8vw";
var headers = document.getElementsByClassName('header');
for(var j=0; j<headers.length; j++) {
headers[j].style.height= "6vw";
}
}
if (roomsToshow == 3) {
document.getElementById("square_" + rooms[property].id).style.width = "4vw";
document.getElementById("square_" + rooms[property].id).style.height = "4vw";
document.getElementById("roomHeader_" + rooms[property].id).style.fontSize = "1.2vw";
document.getElementById("freeSeatsHeader_" + rooms[property].id).style.fontSize = "2.5vw";
document.getElementById("courseHeading_" + rooms[property].id).style.fontSize = "1.2vw";
var headers = document.getElementsByClassName('header');
for(var j=0; j<headers.length; j++) {
headers[j].style.height= "4vw";
}
}
if (roomsToshow == 4) {
document.getElementById("square_" + rooms[property].id).style.width = "4vw";
document.getElementById("square_" + rooms[property].id).style.height = "4vw";
document.getElementById("roomHeader_" + rooms[property].id).style.fontSize = "1.5vw";
document.getElementById("freeSeatsHeader_" + rooms[property].id).style.fontSize = "2.5vw";
document.getElementById("courseHeading_" + rooms[property].id).style.fontSize = "1.5vw";
var headers = document.getElementsByClassName('header');
for(var j=0; j<headers.length; j++) {
headers[j].style.height= "4vw";
}
}
if (rooms[property].config.mode == 1) {
setUpCalendar(rooms[property].config.scale + "%", rooms[property].config.daystoshow, rooms[property]);
preInitRoom(rooms[property]);
} else if (rooms[property].config.mode == 2) {
setUpCalendar("100%", rooms[property].config.daystoshow, rooms[property]);
} else if (rooms[property].config.mode == 3) {
preInitRoom(rooms[property]);
getOpeningTimes(rooms[property]);
} else if (rooms[property].config.mode == 4) {
setUpCalendar("100%", rooms[property].config.daystoshow, rooms[property]);
preInitRoom(rooms[property]);
generateProgressBar(rooms[property].id);
}
i++;
}
setInterval(mainUpdateLoop, 1000);
}
function addIdToUpdateList(list,id) {
if(list=="") {
list += id;
} else {
list +=(","+ id);
}
return list;
}
// Main Update loop, this loop runs every 1 seconds and calls all
// function which should be called periodically
var timeSteps = 10;
function mainUpdateLoop() {
// check ervery 10 sec if rooms need new calendar data or room data
// groups request
if(timeSteps > 9) {
timeSteps = 0;
var calendarUpdateIds ="";
var rommUpdateIds="";
for (var property in rooms) {
if (rooms[property].config.lastCalendarUpdate == null || rooms[property].config.lastCalendarUpdate + rooms[property].config.calupdate < MyDate().getTime()) {
calendarUpdateIds = addIdToUpdateList(calendarUpdateIds,rooms[property].id);
rooms[property].config.lastCalendarUpdate = MyDate().getTime();
}
if (rooms[property].config.lastRoomUpdate == null || rooms[property].config.lastRoomUpdate + rooms[property].config.roomupdate < MyDate().getTime()) {
rommUpdateIds= addIdToUpdateList(rommUpdateIds,rooms[property].id);
rooms[property].config.lastRoomUpdate = MyDate().getTime();
}
}
if (calendarUpdateIds != "") {
queryCalendars(calendarUpdateIds);
}
if (rommUpdateIds != "") {
queryRooms(rommUpdateIds);
}
}
// switches calendar and roomlayout in mode 4
for (var property in rooms) {
if (rooms[property].config.mode == 4) {
if (rooms[property].lastSwitchTime == null
|| rooms[property].lastSwitchTime + rooms[property].config.switchtime * 1000 < MyDate().getTime()) {
switchLayout(rooms[property]);
MoveProgressBar(rooms[property].id, rooms[property].config.switchtime);
if (rooms[property].lastSwitchTime == null) {
rooms[property].lastSwitchTime = MyDate().getTime();
} else {
rooms[property].lastSwitchTime = rooms[property].lastSwitchTime + rooms[property].config.switchtime * 1000;
}
}
//
}
// Updateing All room Headers
UpdateRoomHeader(rooms[property]);
}
// reload site at midnight
var now = new MyDate();
if (date != null) {
if (date.getDate() != now.getDate()) {
location.reload(true);
}
}
date = now;
timeSteps++;
}
// Generates a room Object and adds it to the rooms array
function addRoom(id, name, config) {
var room = {
id: id,
name: name,
timetable: null,
currentEvent: null,
nextEventEnd: null,
timeTilFree: null,
state: null,
openingTimes: null,
config: config,
currentfreePcs: 0,
layout: null,
freePcs: 0,
resized: false,
lastCalendarUpdate:null,
lastRoomUpdate:null,
getState: function () {
if (this.state == null) {
ComputeCurrentState(this);
return this.state;
}
if (this.state.end != "") {
if (this.state.end < new MyDate()) {
ComputeCurrentState(this);
}
}
return this.state;
}
}
getParamerter(room);
rooms[id] = room;
return room;
}
// inilizes the Calendar for an room
function setUpCalendar(percent, daysToShow, room) {
generateCalendarDiv(percent, room);
var $calendar = $("#calendar_" + room.id).weekCalendar({
timeslotsPerHour: 1,
timeslotHeight: 30,
daysToShow: daysToShow,
height: function ($calendar) {
var height = $(window).height();
if(roomsToshow == 4) {
height = height/2;
}
height = height- document.getElementById('header_' + room.id).clientHeight - 5;
if (room.config.mode == 1 && room.config.vertical) {
height = height * (room.config.scale / 100)
}
return height;
},
eventRender: function (calEvent, $event) {
if (calEvent.end.getTime() < new MyDate().getTime()) {
$event.css("backgroundColor", "#aaa");
$event.find(".time").css({"backgroundColor": "#999", "border": "1px solid #888"});
} else if (calEvent.end.getTime() > new MyDate().getTime() && calEvent.start.getTime() < new MyDate().getTime()) {
$event.css("backgroundColor", "#25B002");
$event.find(".time").css({"backgroundColor": "#25B002", "border": "1px solid #888"});
}
},
date: MyDate(),
dateFormat: "j.n",
timeFormat: "G:i",
scrollToHourMillis:500,
use24Hour: true,
readonly: true,
showHeader: false,
hourLine: true,
shortDays: t("shortDays"),
longDays: t("longDays"),
buttons: false,
timeSeparator: " " + t("to") + " ",
startOnFirstDayOfWeek: false,
displayFreeBusys: true,
defaultFreeBusy: {free: false}
});
getOpeningTimes(room);
}
// downloads openingTimes for an room
function getOpeningTimes(room) {
$.getJSON("../../../api.php?do=locationinfo&action=openingtime&id=" + room.id, function (result) {
if(Object.prototype.toString.call( result ) === '[object Array]' ) {
if(result.length > 0){
SetOpeningTimes(result[0].openingtime, room);
}
}
scaleCalendar(room);
})
.error(function () {
scaleCalendar(room);
})
}
function generateCalendarDiv(width, room) {
var div = document.createElement("div");
div.id = "calendar_" + room.id;
div.className = "calendar";
if (room.config.vertical && room.config.mode == 1) {
width = 100 + "%";
div.float = "Top";
}
div.style.width = width;
//document.body.appendChild(div);
$("#room_" + room.id).append(div);
}
// sets the opening Time in the calendar plugin and saves it in the room object
function SetOpeningTimes(parsedOpenings, room) {
var opening = 24;
var close = 0;
room.openingTimesCalendar = [];
room.openingTimes = [parsedOpenings['Sunday'], parsedOpenings['Monday'], parsedOpenings['Tuesday'],
parsedOpenings['Wednesday'], parsedOpenings['Thursday'],
parsedOpenings['Friday'], parsedOpenings['Saturday']];
if (room.config.mode == 3) {
return;
}
for (var i = 0; i < 7; i++) {
var tmp = room.openingTimes[i];
if (tmp != null) {
for (var d = 0; d < tmp.length; d++) {
var day = getNextDayOfWeek(new MyDate(), i);
room.openingTimesCalendar.push({
"start": new Date(day.getFullYear(), day.getMonth(), day.getDate(),
tmp[d]['HourOpen'], tmp[d]['MinutesOpen']),
"end": new Date(day.getFullYear(), day.getMonth(),
day.getDate(), tmp[d]['HourClose'], tmp[d]['MinutesClose']),
"free": true
});
if (parseInt(tmp[d]['HourOpen']) < opening) {
opening = tmp[d]['HourOpen'];
}
if (parseInt(tmp[d]['HourClose']) > close) {
close = tmp[d]['HourClose'];
if (parseInt(tmp[d]['MinutesClose']) != 0) {
close++;
}
}
}
}
}
if (parsedOpenings.length == 0) {
opening = 0;
close = 24;
}
room.openTimes = close - opening;
$('#calendar_' + room.id).weekCalendar("option", "businessHours", {
start: parseInt(opening),
end: parseInt(close),
limitDisplay: true
});
}
// querys the Calendar data
function queryCalendars(ids) {
var url = "../../../api.php?do=locationinfo&action=calendar&id=" + ids;
// Todo reimplement Frontend methode if needed
/*
if(!(room.config.calendarqueryurl === undefined)) {
url = room.config.calendarqueryurl;
}
*/
$.ajax({
url: url,
dataType: 'json',
cache: false,
timeout: 30000,
success: function (result) {
var l = result.length;
for (var i = 0; i < l; i++) {
updateCalendar(result[i].calendar, rooms[result[i].id]);
}
}, error: function () {
}
});
}
// applays new calendar data to the calendar plugin and also saves it to the room object
function updateCalendar(json, room) {
if (json == "") {
console.log("Error: Calendar data was an empty string.");
return;
}
try {
room.timetable = json;
if (room.config.mode != 3) {
var cal = $('#calendar_' + room.id);
cal.weekCalendar("option", "data", json);
cal.weekCalendar("refresh");
cal.weekCalendar("option", "defaultFreeBusy", {free: false});
cal.weekCalendar("updateFreeBusy", room.openingTimesCalendar);
}
ComputeCurrentState(room);
} catch (e) {
console.log("Error: Couldnt add calendar data");
console.log(e);
}
}
// scales calendar, called once on create and on window resize
function scaleCalendar(room) {
if (room.config.mode == 3){
return;
}
if (room.openTimes == null) {
room.openTimes = 24;
}
var cal = $('#calendar_' + room.id);
var columnWidth = document.getElementById("calendar_" + room.id).getElementsByClassName("wc-day-1")[0].clientWidth;
if (room.config.scaledaysauto) {
var result = (cal.weekCalendar("option", "daysToShow") * columnWidth) / 100;
result = parseInt(Math.min(Math.max(Math.abs(result), 1), 7));
if (result != parseInt(cal.weekCalendar("option", "daysToShow"))) {
cal.weekCalendar("option", "daysToShow", Math.abs(result));
}
}
if (((!room.config.scaledaysauto) || cal.weekCalendar("option", "daysToShow") == 1) && columnWidth < 85) {
cal.weekCalendar("option", "useShortDayNames", true);
} else {
cal.weekCalendar("option", "useShortDayNames", false);
}
var clientHeight = $(window).height();
if(roomsToshow == 4) {
clientHeight = clientHeight/2;
}
clientHeight = clientHeight - document.getElementById('header_' + room.id).clientHeight
- document.getElementsByClassName("wc-time-column-header")[0].clientHeight -2;
if (roomsToshow > 1) {
clientHeight -= 5;
}
if (room.config.mode == 1 && room.config.vertical) {
clientHeight = clientHeight * (room.config.scale / 100);
clientHeight -= 22;
}
var height = clientHeight / (room.openTimes * cal.weekCalendar("option", "timeslotsPerHour"));
if(height < 30){
height = 30;
}
cal.weekCalendar("option", "timeslotHeight", height);
if(room.openingTimesCalendar != null) {
cal.weekCalendar("updateFreeBusy", room.openingTimesCalendar);
}
cal.weekCalendar("resizeCalendar");
}
// used for countdown
// computes the time difference between 2 Date objects
function GetTimeDiferenceAsString(a, b, room) {
if (a == null || b == null) {
return "";
}
var milliseconds = a.getTime() - b.getTime();
var seconds = Math.floor((milliseconds / 1000) % 60);
milliseconds -= seconds * 1000;
var minutes = Math.floor((milliseconds / (1000 * 60)) % 60);
milliseconds -= minutes * 1000 * 60;
var hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24);
var days = Math.floor((milliseconds / (1000 * 60 * 60 * 24)) % 31);
if (seconds < 10) {
seconds = "0" + seconds;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
if (days != 0) {
// dont show?
return "";
}
if (room.config.einkmode) {
return hours + ":" + minutes;
}
return hours + ":" + minutes + ":" + seconds;
}
// returns next cloesing time of a given room
function GetNextClosing(room) {
var now = new MyDate();
var day = now.getDay();
var offset = 0;
var bestdate;
for (var a = 0; a < 7; a++) {
var tmp = room.openingTimes[day];
if (tmp != null) {
for (var i = 0; i < tmp.length; i++) {
var closeDate = new MyDate();
closeDate.setDate(now.getDate() + offset);
closeDate.setHours(tmp[i].HourClose);
closeDate.setMinutes(tmp[i].MinutesClose);
closeDate.setSeconds(0);
if (closeDate > now) {
if (!IsOpen(new Date(closeDate.getTime() + 60000), room)) {
if (bestdate == null || bestdate > closeDate) {
bestdate = closeDate;
}
}
}
}
}
offset++;
day++;
if (day > 6) {
day = 0;
}
}
return bestdate;
}
// Checks if given room is open now
function IsOpenNow(room) {
var now = new MyDate();
if (room.openingTimes == null) {
return false;
}
var tmp = room.openingTimes[now.getDay()];
if (tmp == null) {
return false;
}
for (var i = 0; i < tmp.length; i++) {
var openDate = new MyDate();
openDate.setHours(tmp[i].HourOpen);
openDate.setMinutes(tmp[i].MinutesOpen);
var closeDate = new MyDate();
closeDate.setHours(tmp[i].HourClose);
closeDate.setMinutes(tmp[i].MinutesClose);
if (openDate < now && closeDate > now) {
return true;
}
}
return false;
}
// checks if a room is on a given date/time open
function IsOpen(date, room) {
if (room.openingTimes == null) {
return false;
}
var tmp = room.openingTimes[date.getDay()];
if (tmp == null) {
return false;
}
for (var i = 0; i < tmp.length; i++) {
var openDate = new MyDate();
openDate.setHours(tmp[i].HourOpen);
openDate.setMinutes(tmp[i].MinutesOpen);
var closeDate = new MyDate();
closeDate.setHours(tmp[i].HourClose);
closeDate.setMinutes(tmp[i].MinutesClose);
if (openDate < date && closeDate > date) {
return true;
}
}
return false;
}
function GetNextOpening(room) {
var now = new MyDate();
var day = now.getDay();
var offset = 0;
var bestdate;
for (var a = 0; a < 7; a++) {
if (room.openingTimes == null) {
return null;
}
var tmp = room.openingTimes[day];
if (tmp != null) {
for (var i = 0; i < tmp.length; i++) {
var openDate = new MyDate();
openDate.setDate(now.getDate() + offset);
openDate.setHours(tmp[i].HourOpen);
openDate.setMinutes(tmp[i].MinutesOpen);
if (openDate > now) {
if (!IsOpen(new Date(openDate.getTime() - 60000), room)) {
if (bestdate == null || bestdate > openDate) {
bestdate = openDate;
}
}
}
}
}
offset++;
day++;
if (day > 6) {
day = 0;
}
}
return bestdate;
}
// sets Header Text of a room
function SetFreeSeats(id, seats) {
if (seats > 0) {
$("#freeSeatsHeader_" + id).text(seats);
$("#square_" + id).css('background-color', '#00dd10');
} else if (seats == -1) {
$("#freeSeatsHeader_" + id).text("");
$("#square_" + id).css('background-color', 'red');
} else {
$("#freeSeatsHeader_" + id).text("0");
$("#square_" + id).css('background-color', 'red');
}
}
function UpdateRoomHeader(room) {
var tmp = room.getState();
if (tmp.state == "closed") {
$("#courseHeading_" + room.id).text(t("closed") + " " + GetTimeDiferenceAsString(tmp.end, new MyDate(), room));
SetFreeSeats(room.id, room.freePcs);
} else if (tmp.state == "ClaendarEvent") {
$("#courseHeading_" + room.id).text(tmp.title);
SetFreeSeats(room.id, -1);
} else if (tmp.state == "Free") {
$("#courseHeading_" + room.id).text(t("free") + " " + GetTimeDiferenceAsString(tmp.end, new MyDate(), room));
SetFreeSeats(room.id, room.freePcs);
} else if (tmp.state == "FreeNoEnd") {
$("#courseHeading_" + room.id).text(t("free"));
SetFreeSeats(room.id, room.freePcs);
}
}
// computes state of a room, states are:
// closed, FreeNoEnd, Free, ClaendarEvent.
function ComputeCurrentState(room) {
if (!IsOpenNow(room)) {
room.state = {state: "closed", end: GetNextOpening(room), title: "", next: ""};
return;
}
var closing = GetNextClosing(room);
var event = getNextEvent(room.timetable);
// no event and no closing
if (closing == null && event == null) {
room.state = {state: "FreeNoEnd", end: "", title: "", next: ""};
return;
}
// no event so closing is next
if (event == null) {
room.state = {state: "Free", end: closing, title: "", next: "closing"};
return;
}
// event is at the moment
if ((closing == null || event.start.getTime() < closing.getTime()) && event.start.getTime() < new MyDate()) {
room.state = {state: "ClaendarEvent", end: event.end, title: event.title, next: ""};
return;
}
// no closing so event is next
if (closing == null) {
room.state = {state: "Free", end: event.start, title: "", next: "event"};
return;
}
// event sooner then closing
if (event.start.getTime() < closing) {
room.state = {state: "Free", end: event.start, title: "", next: "event"};
} else if (event.start.getTime() > closing) {
room.state = {state: "Free", end: closing, title: "", next: "closing"};
}
}
// returns next event from a given json of events
function getNextEvent(json) {
var event;
var now = new MyDate();
if (json == null) {
return;
}
for (var i = 0; i < json.length; i++) {
//event is now active
if (json[i].start.getTime() < now.getTime() && json[i].end.getTime() > now.getTime()) {
return json[i];
}
//first element to consider
if (event == null) {
if (json[i].start.getTime() > now.getTime()) {
event = json[i];
}
}
if (json[i].start.getTime() > now.getTime() && event.start.getTime() > json[i].start.getTime()) {
event = json[i];
}
}
return event;
}
function getNextDayOfWeek(date, dayOfWeek) {
// Code to check that date and dayOfWeek are valid left as an exercise ;)
var resultDate = new Date(date.getTime());
resultDate.setDate(date.getDate() + (7 + dayOfWeek - date.getDay()) % 7);
return resultDate;
}
/*
/========================================== Room Layout =============================================
*/
var picSizeX = 3.8;
var picSizeY = 3;
function generateRoomLayoutDiv(width, room) {
var div = document.createElement("div");
div.id = "roomLayout_" + room.id;
div.className = "roomLayoutDesign";
if ((room.config.vertical && room.config.mode == 1) || (room.config.mode == 3) || (room.config.mode == 4)) {
width = 100 + "%";
div.float = "Top";
}
div.style.width = width;
//document.body.appendChild(div);
$("#room_" + room.id).append(div);
}
function preInitRoom(room) {
$.getJSON("../../../api.php?do=locationinfo&action=roominfo&id=" + room.id + "&coords=1", function (result) {
generateRoomLayoutDiv((100 - room.config.scale) + "%", room);
if (result[0] == null) {
return;
}
initRoom(result[0].computer, (100 - room.config.scale) + "%", room);
}).error(function () {
generateRoomLayoutDiv((100 - room.config.scale) + "%", room);
})
}
// Main funciton for generating the Room Layout
function initRoom(layout, scale, room) {
var maxX;
var maxY;
var minY;
var minX;
var xDifference;
var yDifference;
room.layout = layout;
if (layout == null || layout.length == 0) {
return;
}
if (room.config.rotation != 0) {
rotateRoom(room.config.rotation, layout);
}
for (var i = 0; i < layout.length; i++) {
if (!isNaN(parseInt(layout[i].x)) && !isNaN(parseInt(layout[i].y)) && layout[i].y != null && layout[i].y != null) {
if (minX === undefined) {
minX = parseInt(layout[i].x);
}
if (minY === undefined) {
minY = parseInt(layout[i].y);
}
if (maxX === undefined) {
maxX = parseInt(layout[i].x);
}
if (maxY === undefined) {
maxY = parseInt(layout[i].y);
}
if (parseInt(layout[i].x) < parseInt(minX)) {
minX = parseInt(layout[i].x);
}
if (parseInt(layout[i].y) < parseInt(minY)) {
minY = parseInt(layout[i].y);
}
if (parseInt(layout[i].x) > parseInt(maxX)) {
maxX = parseInt(layout[i].x);
}
if (parseInt(layout[i].y) > parseInt(maxY)) {
maxY = parseInt(layout[i].y);
}
}
}
xDifference = maxX - minX;
yDifference = maxY - minY;
room.xDifference = xDifference;
room.yDifference = yDifference;
room.minX = minX;
room.minY = minY;
room.maxX = maxX;
room.maxY = maxY;
generateOffsetAndScale(room);
setUpRoom(room, layout);
scaleRoom(room);
UpdatePc(layout, room);
}
function generateOffsetAndScale(room) {
var clientHeight = $(window).height();
if(roomsToshow == 4) {
clientHeight = clientHeight/2;
}
clientHeight = clientHeight- document.getElementById('header_' + room.id).clientHeight - 5;
if (roomsToshow > 1) {
clientHeight -= 5;
}
if (room.config.vertical && room.config.mode == 1) {
clientHeight = clientHeight * (1 - (room.config.scale / 100));
}
var roomLayout = document.getElementById('roomLayout_' + room.id);
var clientWidth = roomLayout.clientWidth;
roomLayout.style.height = clientHeight + "px";
var scaleX;
if (room.xDifference != 0) {
scaleX = clientWidth / room.xDifference;
} else {
scaleX = clientWidth;
}
var scaleY;
if (room.yDifference != 0) {
scaleY = clientHeight / room.yDifference;
} else {
scaleY = clientHeight;
}
var scaleYs = (clientHeight - (picSizeY * scaleY)) / room.yDifference;
var scaleXs = (clientWidth - (picSizeX * scaleX)) / room.xDifference;
if (scaleYs <= 0) {
scaleYs = 9999;
}
if (scaleXs <= 0) {
scaleXs = 9999;
}
var tmp = [scaleYs, scaleY, scaleXs, scaleX,(clientHeight *0.9) / picSizeY,(clientWidth *0.9) / picSizeX];
room.scale = Math.min.apply(Math, tmp);
room.xOffset = 0 - room.minX;
room.yOffset = 0 - room.minY;
room.xOffset += ((1 / 2 * (clientWidth - (((room.maxX + room.xOffset) * room.scale) + picSizeX * room.scale))) / room.scale);
room.yOffset += ((1 / 2 * (clientHeight - (((room.maxY + room.yOffset) * room.scale) + picSizeY * room.scale))) / room.scale);
}
// adds images for each pc to Room Layout
function setUpRoom(room, layout) {
for (var i = 0; i < layout.length; i++) {
if (layout[i].y != null && layout[i].x != null && !isNaN(layout[i].y) && !isNaN(layout[i].x)) {
var text = "<div class= 'PCImgDiv' id ='layout_PC_div_" + room.id + "_"+layout[i].id +"'>" +
"<div class= 'OverlayDiv' id ='layout_PC_overlay_"+ room.id + "_"+layout[i].id +"'>" +
"</div>"+
"<img class= 'pcImg' id ='layout_PC_" + room.id + "_"+layout[i].id +"'> </img>" +
"</div>";
$('#roomLayout_' + room.id).append(text);
if(layout[i].hasOwnProperty('overlay')) {
for (var a = 0; a < layout[i].overlay.length; a++) {
addOverlay($('#layout_PC_overlay_' + room.id + "_" + layout[i].id), layout[i].overlay[a]);
}
}
}
}
}
function addOverlay(object,overlayName) {
var a = [".svg",".png","jpg"];
var imgname;
for (var i = 0; i < a.length; a++ ) {
if(imageExists("img/overlay/" + overlayName + a[i])) {
imgname = "img/overlay/" + overlayName + a[i];
break;
}
}
if(imgname == null)
{
return;
}
var text = $("<img class='overlay' src='"+ imgname+"'></img>");
text.addClass("overlay-"+overlayName);
object.append(text);
}
var imgExists = {};
// checks if images exists (chaches it also)
function imageExists(image_url){
if(!imgExists.hasOwnProperty(image_url))
{
var http = new XMLHttpRequest();
http.open('HEAD', image_url, false);
http.send();
imgExists[image_url] = http.status != 404;
}
return imgExists[image_url];
}
// querys Pc states
function queryRooms(ids) {
$.ajax({
url: "../../../api.php?do=locationinfo&action=roominfo&id=" + ids + "&coords=0",
dataType: 'json',
cache: false,
timeout: 30000,
success: function (result) {
var l = result.length;
if(result[0]== null){
console.log("Error: Backend reported null back for RoomUpdate, this might happend if the room isn't" +
"configurated.");
return;
}
for (var i = 0; i < l; i++) {
UpdatePc(result[i].computer, rooms[result[i].id]);
}
}, error: function () {
}
})
}
// adjust pc coordinate depending on room rotation
function rotateRoom(r, layout) {
for (var z = 0; z < r; z++) {
for (var i = 0; i < layout.length; i++) {
var x = parseInt(layout[i].x);
var y = parseInt(layout[i].y);
layout[i].x = y;
layout[i].y = -x;
}
}
}
// Positions the computer images in the roomLayout div accoring to ther potion and div size
function scaleRoom(room) {
if (room.layout == null) {
return;
}
for (var i = 0; i < room.layout.length; i++) {
if (room.layout[i].y != null && room.layout[i].x != null && !isNaN(room.layout[i].y) && !isNaN(room.layout[i].x)) {
var tmp = document.getElementById("layout_PC_div_" + room.id + "_" + room.layout[i].id);
var img = document.getElementById("layout_PC_" + room.id + "_" + room.layout[i].id);
if (tmp != null) {
tmp.style.width = (picSizeX * room.scale);
tmp.setAttribute("style","width:"+(picSizeX * room.scale)+"px");
tmp.style.height = (picSizeY * room.scale)+"px";
tmp.style.left = ((parseInt(room.layout[i].x) + room.xOffset) * room.scale) + "px";
tmp.style.top = ((parseInt(room.layout[i].y) + room.yOffset) * room.scale ) + "px";
}
}
}
}
// Updates the images of the pcs
// also computes how much pcs are free
function UpdatePc(update, room) {
if (update === undefined || update == null) {
return;
}
var freePcs = 0;
for (var i = 0; i < update.length; i++) {
var imgobj = document.getElementById("layout_PC_" + room.id + "_" + update[i].id);
var img;
// Pc free
if (update[i].pcState == "0") {
if (supportSvg) {
img = "img/pc_free";
} else {
imgobj.style.backgroundColor = "green";
}
freePcs++;
// Pc in use
} else if (update[i].pcState == "1") {
if (supportSvg) {
img = "img/pc_used";
} else {
imgobj.style.backgroundColor = "red";
}
// PC off
} else if (update[i].pcState == "2") {
if (supportSvg) {
img = "img/pc_off";
} else {
imgobj.style.backgroundColor = "black";
}
freePcs++;
} else {
if (supportSvg) {
img = "img/pc_defect";
} else {
imgobj.style.backgroundColor = "black";
}
}
if (imgobj != null && supportSvg) {
if (room.config.einkmode) {
img = img + "_eink";
}
imgobj.src = img + ".svg";
}
}
room.freePcs = freePcs;
}
/*
/========================================== Misc =============================================
*/
var resizeTimeout;
// called when browser window changes size
// scales calendar and room layout acordingly
$(window).resize(function () {
clearTimeout(resizeTimeout);
resizeTimeout =setTimeout(function () {
for (var property in rooms) {
rooms[property].resized = true;
if (rooms[property].config.mode != null) {
if (rooms[property].config.mode != 3) {
scaleCalendar(rooms[property]);
}
if (rooms[property].config.mode != 2) {
generateOffsetAndScale(rooms[property]);
scaleRoom(rooms[property]);
}
}
}
}, 50);
});
// returns parameter value from the url
var getUrlParameter = function getUrlParameter(sParam) {
var sPageURL = decodeURIComponent(window.location.search.substring(1)),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : sParameterName[1];
}
}
};
function t(toTranslate) {
var r = translation[$('html')[0].lang][toTranslate];
if (r === undefined) {
r = translation['en'][toTranslate]
}
return r;
}
// switches from calendar to room and vice versa, used in mode 4
function switchLayout(room) {
var car = document.getElementById("calendar_" + room.id);
var roomLayout = document.getElementById("roomLayout_" + room.id);
if (car.style.display == "none") {
roomLayout.style.display = "none";
car.style.display = "block";
if (room.resized) {
scaleCalendar(room);
room.resized = false;
}
} else {
car.style.display = "none";
roomLayout.style.display = "block";
if (room.resized) {
generateOffsetAndScale(room);
scaleRoom(room);
room.resized = false;
}
}
}
// adds a progressbar to a given room (id) used in mode 4
function generateProgressBar(id) {
var div = document.createElement("div");
div.id = "progressBar_" + id;
div.classList.add("progressbar");
//document.body.appendChild(div);
$("#room_" + id).append(div);
}
function MoveProgressBar(roomId, time) {
var elem = document.getElementById("progressBar_" + roomId);
var width = 1;
var id = setInterval(frame, time * 10);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
}
}
}
</script>
</head>
<body>
</body>
</html>