diff options
author | Simon Rettberg | 2017-06-20 15:36:37 +0200 |
---|---|---|
committer | Simon Rettberg | 2017-06-20 15:36:37 +0200 |
commit | da9e025f2b8aa7984782ea86f534530a7c0972f0 (patch) | |
tree | e96701748e4ea8ef5db1c164f99628b739938ec5 /modules-available/locationinfo/frontend | |
parent | [locationinfo] Frontend mostly working again... (diff) | |
download | slx-admin-da9e025f2b8aa7984782ea86f534530a7c0972f0.tar.gz slx-admin-da9e025f2b8aa7984782ea86f534530a7c0972f0.tar.xz slx-admin-da9e025f2b8aa7984782ea86f534530a7c0972f0.zip |
[locationinfo] Finish doorsign.html
Diffstat (limited to 'modules-available/locationinfo/frontend')
-rwxr-xr-x | modules-available/locationinfo/frontend/doorsign.html | 2759 |
1 files changed, 1364 insertions, 1395 deletions
diff --git a/modules-available/locationinfo/frontend/doorsign.html b/modules-available/locationinfo/frontend/doorsign.html index eb15c9d0..a39b982a 100755 --- a/modules-available/locationinfo/frontend/doorsign.html +++ b/modules-available/locationinfo/frontend/doorsign.html @@ -20,113 +20,131 @@ optional: 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 - scaledaysauto: [true] if true it finds automaticly the daystoshow parameter depending on display size + scaledaysauto: [true] if true it finds automatically the daystoshow parameter depending on display size --> <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; + padding: 0; width: 100%; height: 100%; - float: left; - box-sizing: border-box; - background-color: #cacaca; overflow: hidden; position: absolute; display: table; - } .row { - background-color: #404040; + background-color: #444; box-shadow: 0 0.1875rem 0.375rem rgba(0, 0, 0, 0.25); margin-bottom: 4px; - width: 100%; - + display: flex; + flex-wrap: nowrap; + align-items: center; + justify-content: space-between; } - .header { - display: table; + .col { + padding: 0 4px; color: white; - padding: 0; + overflow: hidden; + flex: 1 1 auto; + text-overflow: ellipsis; + } + + .col-square { + width: 4vw; + height: 4vw; + font-size: 2.5vw; + flex: 0 0 auto; + text-align: center; + padding: 5px 0 0 0; + } + + .count-1 .col-square { + width: 8vw; height: 8vw; + font-size: 6vw; + } + .count-2 .col-square { + width: 6vw; + height: 6vw; + font-size: 4.5vw; } .progressbar { - width: 0px; + width: 0; height: 2px; position: absolute; background-color: red; - bottom: 0px; + bottom: 0; z-index: 100; } - .font { - display: table-cell; - vertical-align: middle; + .header-font { font-size: 3vw; - font-weight: bold + font-weight: bold; } - .courseText { - text-align: center; + .nowrap { + white-space: nowrap; + overflow: hidden; } - .row::after { - content: ""; - clear: both; - display: block; + .timer { + color: #ddd; } - [class|="col"] { - float: left; - padding: 0; - box-sizing: border-box; + .count-2 .header-font { + font-size: 1.8vw; } - .col-1 { - width: 33%; + .count-3 .header-font { + font-size: 1.2vw; } - .col-2 { - width: 33%; + .count-1 .header-font { + font-size: 1.5vw; } - .roomLayoutDesign { - position: relative; - float: left; - boxSizing: border-box; + .seats-counter { + color: white; + margin: auto; + padding: 0; + font-weight: bold; + overflow: visible; + height: 100%; + text-shadow: #000 2px 2px; } - .roompadding { - float: left; - position: relative; + .center { + text-align: center; } - .room { + .room-layout { position: relative; + float: left; + } + + .location-container { + position: absolute; background-color: white; width: 100%; height: 100%; overflow: hidden; - border-width: 1px; - border-color: darkgrey; - border-style: solid; + border: 1px solid darkgrey; } @@ -155,28 +173,7 @@ optional: 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 { + .pc-container { position: absolute; left: 0; bottom: 0; @@ -184,7 +181,7 @@ optional: } - .OverlayDiv { + .pc-overlay-container { position: absolute; left: 0; bottom: 0; @@ -193,7 +190,7 @@ optional: display: table; } - .pcImg { + .pc-img { position: absolute; left: 0; top: 0; @@ -219,10 +216,6 @@ optional: float: left; } - .wc-scrollable-grid { - - } - .ui-widget-content .ui-state-active { font-weight: bold; color: black; @@ -242,25 +235,7 @@ optional: } .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; + border-radius: 0; } .wc-scrollable-grid .wc-day-column-first { @@ -268,1440 +243,1434 @@ optional: } - [class*="wc-day-"] { + [class|="wc-day"] { border-color: grey; } </style> - <script type='text/javascript'> - - var rooms = {}; - var lastRoomUpdate = 0; - var lastCalendarUpdate = 0; - var lastSwitchTime = 0; - var globalConfig = {}; - var roomIds = []; - var panelUuid = false; - var supportSvg = typeof SVGRect !== "undefined"; - // TODO: Get languages from slx-admin - 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", "Freitag", "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" - } - }; + <script type='text/javascript' src='../../../script/jquery.js'></script> + <script type='text/javascript' src='../../js_jqueryui/clientscript.js'></script> + <script type='text/javascript' src="jquery-week-calendar/jquery.weekcalendar.js"></script> +</head> +<body> +</body> - $(document).ready(function () { - var uuid = getUrlParameter("uuid"); - if (!uuid) { - console.log('No panel uuid given'); - $("body").empty().append($('<h1>').text('No panel UUID given.')); - return; - } - getConfig(uuid); - }); +<script type='text/javascript'> + + var rooms = {}; + var lastRoomUpdate = 0; + var lastCalendarUpdate = 0; + var lastSwitchTime = 0; + var hasMode4 = false; + var globalConfig = {}; + var roomIds = []; + var panelUuid = false; + var supportSvg = typeof(SVGRect) !== "undefined"; + // TODO: Get languages from slx-admin + 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", "Freitag", "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 () { + var uuid = getUrlParameter("uuid"); + if (!uuid) { + console.log('No panel uuid given'); + $("body").empty().append($('<h1>').text('No panel UUID given.')); + return; + } + getConfig(uuid); + }); + + /** + * Display given error message and try reloading page once a minute + */ + function fatalError(message) { + $('body').empty().append($('<h1>').text(message)); + window.setInterval(function () { + $.ajax('/').done(function () { + window.location.reload(true); + }).fail(function () { + $('body').append('...'); + }); + }, 60000); + } + + + /** + * Downloads the config of a room, also reloads the page if the config hase changed over time + * @param uuid ID of the room + */ + + function getConfig(uuid) { + $.ajax({ + url: "../../../api.php?do=locationinfo&get=config&uuid=" + uuid, + dataType: 'json', + cache: false, + timeout: 30000, + success: function (result) { + + if (!result.locations || result.locations.constructor !== Array) { + fatalError("Requested panel doesn't contain locations / not array"); + return; + } - /** - * Display given error message and try reloading page once a minute - */ - function fatalError(message) { - $('body').empty().append($('<h1>').text(message)); - window.setInterval(function () { - $.ajax('/').done(function () { - window.location.reload(true); - }).fail(function () { - $('body').append('...'); + var fetchedRooms = result.locations.filter(function (x) { + // filter out if no numeric id, or id already present, or already got 4 locations + if (typeof(x.id) !== 'number' || x.id <= 0 || roomIds.indexOf(x.id) !== -1 || roomIds.length >= 4) + return false; + roomIds.push(x.id); + return true; }); - }, 60000); - } + if (roomIds.length === 0) { + fatalError("List of location ids is empty"); + return; + } - /** - * Downloads the config of a room, also reloads the page if the config hase changed over time - * @param uuid ID of the room - * @param room Room Object, only needed if it already exists - */ + var time = new Date(result.time); + if (isNaN(time.getTime()) || time.getYear() < 2010) { + time = new Date(); + } + SetUpDate(time); + delete result.time; + delete result.locations; - function getConfig(uuid) { - $.ajax({ - url: "../../../api.php?do=locationinfo&get=config&uuid=" + uuid, - dataType: 'json', - cache: false, - timeout: 30000, - success: function (result) { + globalConfig = result; + sanitizeGlobalConfig(); + lastRoomUpdate = MyDate().getTime(); - if (!result.locations || result.locations.constructor !== Array) { - fatalError("Requested panel doesn't contain locations / not array"); - return; - } + for (var i = 0; i < fetchedRooms.length; ++i) { + addRoom(fetchedRooms[i]); + } - var fetchedRooms = result.locations.filter(function (x) { - // filter out if no numeric id, or id already present, or already got 4 locations - if (typeof(x.id) !== 'number' || x.id <= 0 || roomIds.indexOf(x.id) !== -1 || roomIds.length >= 4) - return false; - roomIds.push(x.id); - return true; - }); + initRooms(); + // TODO: Check for changed config using get=timestamp and reload whole page on change + panelUuid = uuid; + + }, error: function () { + fatalError('Could not fetch panel config'); + } + }) + } + + const PARAM_STRING = 1; + const PARAM_INT = 2; + const PARAM_BOOL = 3; + + /** + * Read given parameter from URL, replacing it in the config object if present. + * @param config object config object + * @param property string name of property in object, URL param of same name is being checked + * @param paramType int one of PARAM_STRING, PARAM_INT, PARAM_BOOL + * @param intScaleFactor int optional scale factor that will be applied if paramType == PARAM_INT + */ + function setRoomConfigFromUrl(config, property, paramType, intScaleFactor) { + var val = getUrlParameter(property); + if (val === true || val === false) + return; + if (paramType === PARAM_STRING) { + config[property] = val; + } else if (paramType === PARAM_INT) { + config[property] = parseInt(val); + if (intScaleFactor) { + config[property] *= intScaleFactor; + } + } else if (paramType === PARAM_BOOL) { + val = val.toLowerCase(); + config[property] = val.length > 0 && val !== 'false' && val !== 'off' && val !== '0'; + } else { + console.log('Invalid paramType: ' + paramType); + } + } + + /** + * Put given numeric config property in range min..max (both inclusive), + * if not in range, set to default. + * @param config - object config object + * @param property - string config property + * @param min int - min allowed value (inclusive) + * @param max int - max allowed value (inclusive) + * @param defaultval - default value to use if out of range + * @param scaleFactor int - optional scale factor to apply + */ + function putInRange(config, property, min, max, defaultval, scaleFactor) { + var v = config[property]; + if (!scaleFactor) { + scaleFactor = 1; + } + if (!v || !isFinite(v) || isNaN(v) || v < min * scaleFactor || v > max * scaleFactor) { + config[property] = defaultval * scaleFactor; + } + } + + /** + * gets Additional Parameters from the URL, and from the + * downloaded json. + * also makes sure parameters are in a given range + */ + function sanitizeGlobalConfig() { + sanitizeConfig(globalConfig); + $('html').attr('lang', globalConfig.language); + } + + function sanitizeConfig(config) { + if (config) { + config.switchtime = config.switchtime * 1000; + config.calupdate = config.calupdate * 60 * 1000; + config.roomupdate = config.roomupdate * 1000; + } + + setRoomConfigFromUrl(config, 'calupdate', PARAM_INT, 60 * 1000); + setRoomConfigFromUrl(config, 'roomupdate', PARAM_INT, 1000); + setRoomConfigFromUrl(config, 'daystoshow', PARAM_INT); + setRoomConfigFromUrl(config, 'scaledaysauto', PARAM_BOOL); + setRoomConfigFromUrl(config, 'vertical', PARAM_BOOL); + setRoomConfigFromUrl(config, 'eco', PARAM_BOOL); + + setRoomConfigFromUrl(config, 'scale', PARAM_INT); + setRoomConfigFromUrl(config, 'rotation', PARAM_INT); + setRoomConfigFromUrl(config, 'switchtime', PARAM_INT, 1000); + + // parameter validation + putInRange(config, 'switchtime', 5, 120, 6, 1000); + putInRange(config, 'scale', 10, 90, 50); + putInRange(config, 'daystoshow', 1, 7, 7); + putInRange(config, 'roomupdate', 15, 5 * 60, 60, 1000); + putInRange(config, 'calupdate', 1, 60, 30, 60 * 1000); + putInRange(config, 'mode', 1, 4, 1); + putInRange(config, 'rotation', 0, 3, 0); + } + + /** + * generates the Room divs and calls the needed functions depending on the rooms mode + */ + function initRooms() { + + var width = "100%"; + var height = "100%"; + var top, left; + hasMode4 = (globalConfig.mode === 4); + if (roomIds.length === 2 || roomIds.length === 4) { + width = "50%"; + } + if (roomIds.length === 3) { + width = "33%"; + } + if (roomIds.length === 4) { + height = "50%"; + } + for (var t = 0; t < roomIds.length; t++) { + var rid = roomIds[t]; + var room = rooms[rid]; + if (roomIds.length === 3) { + top = 0; + left = (t * 33) + '%'; + } else { + top = (Math.floor(t / 2) * 50) + '%'; + left = ((t % 2) * 50) + '%'; + } - if (roomIds.length === 0) { - fatalError("List of location ids is empty"); - return; - } + var $loc = $("<div>").prop('id', "location_" + rid).addClass('location-container'); + $loc.css({top: top, left: left, width: width, height: height}); + $("body").append($loc); + room.$.container = $loc; - var time = new Date(result.time); - if (isNaN(time.getTime()) || time.getYear() < 2010) { - time = new Date(); - } - SetUpDate(time); - delete result.time; - delete result.locations; + room.$.locationName = $('<div>').addClass('col').addClass('header-font'); - globalConfig = result; - sanitizeGlobalConfig(); - lastRoomUpdate = MyDate().getTime(); + room.$.currentEvent = $("<span>").addClass('nowrap'); + room.$.currentRemain = $("<span>").addClass('nowrap').addClass('timer'); - for (var i = 0; i < fetchedRooms.length; ++i) { - var r = addRoom(fetchedRooms[i]); - } + room.$.seatsCounter = $('<span>').addClass('seats-counter'); + room.$.seatsBackground = $('<div>').addClass('col col-square').append(room.$.seatsCounter); - initRooms(); - // TODO: Check for changed config using get=timestamp and reload whole page on change - panelUuid = uuid; + var $header = $('<div>').addClass('row').addClass('count-' + roomIds.length); + $header.append(room.$.locationName); + $header.append($('<div>').addClass('col header-font center').append(room.$.currentEvent).append(' ').append(room.$.currentRemain)); + $header.append(room.$.seatsBackground); - }, error: function () { - fatalError('Could not fetch panel config'); - } - }) - } - - const PARAM_STRING = 1; - const PARAM_INT = 2; - const PARAM_BOOL = 3; - - /** - * Read given parameter from URL, replacing it in the config object if present. - * @param config object config object - * @param property string name of property in object, URL param of same name is being checked - * @param paramType int one of PARAM_STRING, PARAM_INT, PARAM_BOOL - * @param intScaleFactor int optional scale factor that will be applied if paramType == PARAM_INT - */ - function setRoomConfigFromUrl(config, property, paramType, intScaleFactor) { - var val = getUrlParameter(property); - if (val === true || val === false) - return; - if (paramType === PARAM_STRING) { - config[property] = val; - } else if (paramType === PARAM_INT) { - config[property] = parseInt(val); - if (intScaleFactor) { - config[property] *= intScaleFactor; - } - } else if (paramType === PARAM_BOOL) { - val = val.toLowerCase(); - config[property] = val.length > 0 && val !== 'false' && val !== 'off' && val !== '0'; - } else { - console.log('Invalid paramType: ' + paramType); - } - } + $loc.append($header); + room.$.header = $header; - /** - * Put given numeric config property in range min..max (both inclusive), - * if not in range, set to default. - * @param config - object config object - * @param property - string config property - * @param min int - min allowed value (inclusive) - * @param max int - max allowed value (inclusive) - * @param defaultval - default value to use if out of range - * @param scaleFactor int - optional scale factor to apply - */ - function putInRange(config, property, min, max, defaultval, scaleFactor) { - var v = config[property]; - if (!scaleFactor) { - scaleFactor = 1; - } - if (!v || !isFinite(v) || isNaN(v) || v < min * scaleFactor || v > max * scaleFactor) { - config[property] = defaultval * scaleFactor; + if (room.name !== null) { + room.$.locationName.text(room.name); } - } - /** - * gets Additional Parameters from the URL, and from the - * downloaded json. - * also makes sure parameters are in a given range - */ - function sanitizeGlobalConfig() { - if (globalConfig) { - globalConfig.switchtime = globalConfig.switchtime * 1000; - globalConfig.calupdate = globalConfig.calupdate * 60 * 1000; - globalConfig.roomupdate = globalConfig.roomupdate * 1000; - } + if (room.config.mode === 1) { + setUpCalendar(room.config.scale + "%", room.config.daystoshow, rooms[rid]); + initRoomLayout(rooms[rid]); - setRoomConfigFromUrl(globalConfig, 'mode', PARAM_INT); - setRoomConfigFromUrl(globalConfig, 'calupdate', PARAM_INT, 60 * 1000); - setRoomConfigFromUrl(globalConfig, 'roomupdate', PARAM_INT, 1000); - setRoomConfigFromUrl(globalConfig, 'daystoshow', PARAM_INT); - setRoomConfigFromUrl(globalConfig, 'scaledaysauto', PARAM_BOOL); - setRoomConfigFromUrl(globalConfig, 'vertical', PARAM_BOOL); - setRoomConfigFromUrl(globalConfig, 'eco', PARAM_BOOL); - - setRoomConfigFromUrl(globalConfig, 'scale', PARAM_INT); - setRoomConfigFromUrl(globalConfig, 'rotation', PARAM_INT); - setRoomConfigFromUrl(globalConfig, 'switchtime', PARAM_INT, 1000); - - // parameter validation - putInRange(globalConfig, 'switchtime', 5, 120, 6, 1000); - putInRange(globalConfig, 'scale', 10, 90, 50); - putInRange(globalConfig, 'daystoshow', 1, 7, 7); - putInRange(globalConfig, 'roomupdate', 15, 5 * 60, 60, 1000); - putInRange(globalConfig, 'calupdate', 1, 60, 30, 60 * 1000); - putInRange(globalConfig, 'mode', 1, 4, 1); - putInRange(globalConfig, 'rotation', 0, 3, 0); - - $('html').attr('lang', globalConfig.language); - } - - /** - * generates the Room divs and calls the needed functions depending on the rooms mode - */ - function initRooms() { - - var width = "100%"; - var height = "100%"; - var hasMode4 = (globalConfig.mode === 4); - if (roomIds.length === 2 || roomIds.length === 4) { - width = "50%"; - } - if (roomIds.length === 3) { - width = "33%"; - } - if (roomIds.length === 4) { - height = "50%"; - } - for (var t = 0; t < roomIds.length; t++) { - var headers; - var rid = roomIds[t]; - var text = "<div class='roompadding' id='roompadding_" + rid + "'></div>"; - $("body").append(text); - - - var obj = document.getElementById("roompadding_" + rid); - obj.style.height = height; - obj.style.width = width; - text = "<div class='room' id ='room_" + rid + "'></div>"; - - $("#roompadding_" + rid).append(text); - - - text = "<div id='header_" + rid + "' class='row'>" + - "<div class='header col-2'>" + - "<div class='font' id='roomHeader_" + rid + "'></div>" + - "</div>" + - "<div class='col-1 courseText header'>" + - "<div class='font' id='courseHeading_" + rid + "'></div>" + - "</div>" + - "<div class='square .col-2' id='square_" + rid + "'>" + - "<div class='FreeSeatsFont' id='freeSeatsHeader_" + rid + "'></div>" + - "</div>" + - "</div>"; - $("#room_" + rid).append(text); - - if (rooms[rid].name !== null) { - $("#roomHeader_" + rid).text(rooms[rid].name); - } + } else if (room.config.mode === 2) { + setUpCalendar("100%", room.config.daystoshow, rooms[rid]); - if (roomIds.length === 2) { - document.getElementById("square_" + rid).style.width = "6vw"; - document.getElementById("square_" + rid).style.height = "6vw"; - document.getElementById("roomHeader_" + rid).style.fontSize = "1.8vw"; - document.getElementById("freeSeatsHeader_" + rid).style.fontSize = "4.5vw"; - document.getElementById("courseHeading_" + rid).style.fontSize = "1.8vw"; - headers = document.getElementsByClassName('header'); - for (var j = 0; j < headers.length; j++) { - headers[j].style.height = "6vw"; - } - } - if (roomIds.length === 3) { - document.getElementById("square_" + rid).style.width = "4vw"; - document.getElementById("square_" + rid).style.height = "4vw"; - document.getElementById("roomHeader_" + rid).style.fontSize = "1.2vw"; - document.getElementById("freeSeatsHeader_" + rid).style.fontSize = "2.5vw"; - document.getElementById("courseHeading_" + rid).style.fontSize = "1.2vw"; - headers = document.getElementsByClassName('header'); - for (var j = 0; j < headers.length; j++) { - headers[j].style.height = "4vw"; - } + } else if (room.config.mode === 3) { + initRoomLayout(rooms[rid]); - } - if (roomIds.length === 4) { - document.getElementById("square_" + rid).style.width = "4vw"; - document.getElementById("square_" + rid).style.height = "4vw"; - document.getElementById("roomHeader_" + rid).style.fontSize = "1.5vw"; - document.getElementById("freeSeatsHeader_" + rid).style.fontSize = "2.5vw"; - document.getElementById("courseHeading_" + rid).style.fontSize = "1.5vw"; - - headers = document.getElementsByClassName('header'); - for (var j = 0; j < headers.length; j++) { - headers[j].style.height = "4vw"; - } - } + } else if (room.config.mode === 4) { + setUpCalendar("100%", room.config.daystoshow, rooms[rid]); + initRoomLayout(rooms[rid]); + hasMode4 = true; + } + SetOpeningTimes(rooms[rid]); + UpdateRoomHeader(rooms[rid]); + (function (room) { + setTimeout(function () { + resizeIfRequired(room); + }, 800); + })(room); + } - if (globalConfig.mode === 1) { - setUpCalendar(globalConfig.scale + "%", globalConfig.daystoshow, rooms[rid]); - initRoomLayout(rooms[rid]); + if (hasMode4) { + generateProgressBar(); + } - } else if (globalConfig.mode === 2) { - setUpCalendar("100%", globalConfig.daystoshow, rooms[rid]); + setInterval(mainUpdateLoop, 1000); + } - } else if (globalConfig.mode === 3) { - initRoomLayout(rooms[rid]); + var timeSteps = 10; + var lastDate = false; + /** + * Main Update loop, this loop runs every 1 seconds and calls all + * function which should be called periodically + */ + function mainUpdateLoop() { + var date = MyDate(); + var now = date.getTime(); + // check every 10 sec if rooms need new calendar data or room data + // groups request - } else if (globalConfig.mode === 4) { - setUpCalendar("100%", globalConfig.daystoshow, rooms[rid]); - initRoomLayout(rooms[rid]); - hasMode4 = true; - } - SetOpeningTimes(rooms[rid]); - UpdateRoomHeader(rooms[rid]); - } + if (timeSteps > 9) { + timeSteps = 0; - if (hasMode4) { - generateProgressBar(); + if (lastCalendarUpdate + globalConfig.calupdate < now) { + lastCalendarUpdate = now; + queryCalendars(); } - setInterval(mainUpdateLoop, 1000); - } - - var timeSteps = 10; - var lastDate = false; - /** - * Main Update loop, this loop runs every 1 seconds and calls all - * function which should be called periodically - */ - function mainUpdateLoop() { - var date = MyDate(); - var now = date.getTime(); - // check ervery 10 sec if rooms need new calendar data or room data - // groups request - - if (timeSteps > 9) { - timeSteps = 0; - - if (lastCalendarUpdate + globalConfig.calupdate < now) { - lastCalendarUpdate = now; - queryCalendars(); - } - if (lastRoomUpdate + globalConfig.roomupdate < now) { - lastRoomUpdate = now; - queryRooms(); - } + if (lastRoomUpdate + globalConfig.roomupdate < now) { + lastRoomUpdate = now; + queryRooms(); } + } - - // switches calendar and roomlayout in mode 4 - if (globalConfig.mode === 4 && lastSwitchTime + globalConfig.switchtime < now) { - doSwitch = true; - lastSwitchTime = now; + for (var property in rooms) { + if (rooms[property].state.end) { + // Updating All room Headers + UpdateRoomHeader(rooms[property]); } + } - for (var property in rooms) { - if (rooms[property].state.end) { - // Updating All room Headers - UpdateRoomHeader(rooms[property]); - } + // reload site at midnight + var today = date.getDate(); + if (lastDate !== false) { + if (lastDate !== today) { + location.reload(true); } + } else { + lastDate = today; + } + timeSteps++; - // reload site at midnight - var today = date.getDate(); - if (lastDate !== false) { - if (lastDate !== today) { - location.reload(true); + } + + /** + * Generates a room Object and adds it to the rooms array + * @param roomData Config Json of the room + */ + function addRoom(roomData) { + var mergedConfig = {}; + if (roomData.config && typeof(roomData.config.constructor) === 'object') { + mergedConfig = roomData.config; + sanitizeConfig(mergedConfig); + } + for (var k in globalConfig) { + if (typeof mergedConfig[k] === 'undefined') { + mergedConfig[k] = globalConfig[k]; + } + } + var now = MyDate().getTime(); + var room = { + id: roomData.id, + name: roomData.name, + config: mergedConfig, + timetable: null, + currentEvent: null, + nextEventEnd: null, + timeTilFree: null, + state: null, + rawOpeningTimes: roomData.openingtime || null, + openingTimes: null, + openTimes: 24, + currentfreePcs: 0, + layout: roomData.machines || null, + freePcs: 0, + resizeRoom: true, + resizeCalendar: true, + lastCalendarUpdate: now, + lastRoomUpdate: now, + $: {}, + getState: function () { + if (this.state === null) { + ComputeCurrentState(this); + return this.state; } - } else { - lastDate = today; - } - timeSteps++; - - } - - /** - * Generates a room Object and adds it to the rooms array - * @param roomData Config Json of the room - */ - function addRoom(roomData) { - var now = MyDate().getTime(); - var room = { - id: roomData.id, - name: roomData.name, - config: globalConfig, - timetable: null, - currentEvent: null, - nextEventEnd: null, - timeTilFree: null, - state: null, - rawOpeningTimes: roomData.openingtime || null, - openingTimes: null, - openTimes: 24, - currentfreePcs: 0, - layout: roomData.machines || null, - freePcs: 0, - resized: true, - lastCalendarUpdate: now, - lastRoomUpdate: now, - getState: function () { - if (this.state === null) { + if (this.state.end) { + if (this.state.end < MyDate()) { ComputeCurrentState(this); - return this.state; - } - if (this.state.end) { - if (this.state.end < MyDate()) { - ComputeCurrentState(this); - } } - return this.state; } + return this.state; + } - }; - rooms[roomData.id] = room; - return room; - } - - /** - * inilizes the Calendar for an room - * @param percent Percentages of how mucht width the Calendar div should get (only used in mode 1) - * @param daysToShow How many days the calendar should show - * @param room Room Object - */ - 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 (roomIds.length == 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() < MyDate().getTime()) { - $event.css("backgroundColor", "#aaa"); - $event.find(".time").css({"backgroundColor": "#999", "border": "1px solid #888"}); - } else if (calEvent.end.getTime() > MyDate().getTime() && calEvent.start.getTime() < 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", room.config.language), - longDays: t("longDays", room.config.language), - buttons: false, - timeSeparator: " " + t("to", room.config.language) + " ", - startOnFirstDayOfWeek: false, - displayFreeBusys: true, - defaultFreeBusy: {free: false} - }); - } - - /** - * Generates the Calendar Div, depending on it's width - * @param width width of the Calendar Div - * @param room Room Object - */ + }; + rooms[roomData.id] = room; + return room; + } + + /** + * inilizes the Calendar for an room + * @param percent Percentages of how mucht width the Calendar div should get (only used in mode 1) + * @param daysToShow How many days the calendar should show + * @param room Room Object + */ + function setUpCalendar(percent, daysToShow, room) { + generateCalendarDiv(percent, room); + room.$.calendar.weekCalendar({ + timeslotsPerHour: 1, + timeslotHeight: 30, + daysToShow: daysToShow, + height: function () { + var height = $(window).height(); + if (roomIds.length === 4) { + height /= 2; + } - 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).css('float', "none"); - } - div.style.width = width; - //document.body.appendChild(div); - $("#room_" + room.id).append(div); - - } - - const OT_DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - const OT_KEYS = ['HourOpen', 'HourClose', 'MinutesOpen', 'MinutesClose']; - - /** - * sets the opening Time in the calendar plugin and saves it in the room object - * @param room Room Object - */ - - function SetOpeningTimes(room) { - var opening = 24; - var close = 0; - var i; - if (room.rawOpeningTimes && typeof(room.rawOpeningTimes) === 'object') { - // TODO: wtf! we have three(!) formats for storing the opening times (DB, API, now this one) - WHY!? - var parsedOpenings = room.rawOpeningTimes; - room.state = null; - room.openingTimesCalendar = []; - room.openingTimes = []; - for (i = 0; i < OT_DAYS.length; ++i) { - room.openingTimes.push(filterOpeningTimesDay(parsedOpenings[OT_DAYS[i]])); + height -= room.$.header.height() - 5; + if (room.config.mode === 1 && room.config.vertical) { + height *= (room.config.scale / 100); } - delete room.rawOpeningTimes; - } - if (!room.openingTimes) { - scaleCalendar(room); - return; - } - if (room.config.mode === 3) { - // Calendar is not displayed, don't need to do additional work - return; - } - var now = MyDate(); - for (i = 0; i < 7; i++) { - var tmp = room.openingTimes[i]; - for (var d = 0; d < tmp.length; d++) { - var day = getNextDayOfWeek(now, i); - if (room.openingTimesCalendar) { - 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 (tmp[d]['HourOpen'] < opening) { - opening = tmp[d]['HourOpen']; - } - if (tmp[d]['HourClose'] >= close) { - close = tmp[d]['HourClose']; - if (tmp[d]['MinutesClose'] !== 0) { - close++; - } - } + return height; + }, + eventRender: function (calEvent, $event) { + if (calEvent.end.getTime() < MyDate().getTime()) { + $event.css("backgroundColor", "#aaa"); + $event.find(".time").css({"backgroundColor": "#999", "border": "1px solid #888"}); + } else if (calEvent.end.getTime() > MyDate().getTime() && calEvent.start.getTime() < MyDate().getTime()) { + $event.css("backgroundColor", "#25B002"); + $event.find(".time").css({"backgroundColor": "#25B002", "border": "1px solid #888"}); } - } - if (opening === 24 && close === 0) { - opening = 0; - close = 24; - } - room.openTimes = close - opening; - $('#calendar_' + room.id).weekCalendar("option", "businessHours", { - start: opening, - end: close, - limitDisplay: true - }); + }, + date: MyDate(), + dateFormat: "j.n", + timeFormat: "G:i", + scrollToHourMillis: 500, + use24Hour: true, + readonly: true, + showHeader: false, + hourLine: true, + shortDays: t("shortDays", room.config.language), + longDays: t("longDays", room.config.language), + buttons: false, + timeSeparator: " " + t("to", room.config.language) + " ", + startOnFirstDayOfWeek: false, + displayFreeBusys: true, + defaultFreeBusy: {free: false} + }); + } + + /** + * Generates the Calendar Div, depending on it's width + * @param width width of the Calendar Div + * @param room Room Object + */ + + function generateCalendarDiv(width, room) { + var $cal = $('<div>').prop('id', 'calendar_' + room.id).addClass('calendar'); + if (room.config.vertical && room.config.mode === 1) { + width = 100 + "%"; + $cal.css('float', "none"); + } + $cal.width(width); + room.$.container.append($cal); + room.$.calendar = $cal; + } + + const OT_DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + const OT_KEYS = ['HourOpen', 'HourClose', 'MinutesOpen', 'MinutesClose']; + + /** + * sets the opening Time in the calendar plugin and saves it in the room object + * @param room Room Object + */ + + function SetOpeningTimes(room) { + var opening = 24; + var close = 0; + var i; + if (room.rawOpeningTimes && typeof(room.rawOpeningTimes) === 'object') { + // TODO: wtf! we have three(!) formats for storing the opening times (DB, API, now this one) - WHY!? + var parsedOpenings = room.rawOpeningTimes; + room.state = null; + room.openingTimesCalendar = []; + room.openingTimes = []; + for (i = 0; i < OT_DAYS.length; ++i) { + room.openingTimes.push(filterOpeningTimesDay(parsedOpenings[OT_DAYS[i]])); + } + delete room.rawOpeningTimes; + } + if (!room.openingTimes) { scaleCalendar(room); - } - - /** - * Filter out invalid opening time entries from given array, - * also make sure all the values are of type number (int) - * - * @param {Array} arr - * @return {Array} list of valid opening times - */ - function filterOpeningTimesDay(arr) { - if (!arr || arr.constructor !== Array) return []; - return arr.map(function (el) { - if (!el || typeof el !== 'object') return null; - for (var i = 0; i < OT_KEYS.length; ++i) { - el[OT_KEYS[i]] = toInt(el[OT_KEYS[i]]); - if (isNaN(el[OT_KEYS[i]])) return null; + return; + } + if (room.config.mode === 3) { + // Calendar is not displayed, don't need to do additional work + return; + } + var now = MyDate(); + for (i = 0; i < 7; i++) { + var tmp = room.openingTimes[i]; + for (var d = 0; d < tmp.length; d++) { + var day = getNextDayOfWeek(now, i); + if (room.openingTimesCalendar) { + 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 + }); } - return el; - }).filter(function (el) { - if (!el) return false; - if (el.HourOpen < 0 || el.HourOpen > 23) return false; - if (el.HourClose < 0 || el.HourClose > 23) return false; - if (el.HourClose < el.HourOpen) return false; - if (el.MinutesOpen < 0 || el.MinutesOpen > 59) return false; - if (el.MinutesClose < 0 || el.MinutesClose > 59) return false; - if (el.HourOpen === el.HourClose && el.MinutesClose < el.MinutesOpen) return false; - return true; - }); - } - - /** - * querys the Calendar data - * @param ids ID'S of rooms to query as string, for e.g.: "5,17,8" or "5" - */ - function queryCalendars() { - if (!panelUuid) return; - var url = "../../../api.php?do=locationinfo&get=calendar&uuid=" + panelUuid; - $.ajax({ - url: url, - dataType: 'json', - cache: false, - timeout: 30000, - success: function (result) { - if (result && result.constructor === Array) { - var l = result.length; - for (var i = 0; i < l; i++) { - updateCalendar(result[i].calendar, rooms[result[i].id]); - } - } - }, error: function () { - // Retry in 5 minutes (300 seconds) - lastCalendarUpdate = MyDate().getTime() + globalConfig.calupdate + 300000; + if (tmp[d]['HourOpen'] < opening) { + opening = tmp[d]['HourOpen']; } - }); - } - - const SEVEN_DAYS = 7 * 86400 * 1000; - - /** - * applays new calendar data to the calendar plugin and also saves it to the room object - * @param {Array} json Calendar data - * @param room Room Object - */ - function updateCalendar(json, room) { - if (!room) { - console.log("Error: No room for calendar data"); - return; - } - if (!json || json.constructor !== Array) { - console.log("Error: Calendar data was empty or malformed."); - return; - } - var now = MyDate().getTime(); - json = json.filter(function (el) { - if (!el.title || !el.start || !el.end) return false; - var s = new Date(el.start).getTime(); - var e = new Date(el.end).getTime(); - if (isNaN(s) || isNaN(e) || Math.abs(s - now) > SEVEN_DAYS || Math.abs(e - now) > SEVEN_DAYS) return false; - return true; - }); - if (json.length === 0) { - console.log('Notice: Calendar has no current events for ' + room.name); - } - try { - room.timetable = json; - if (room.config.mode !== 3) { - // TODO: Check if they're the same - var cal = $('#calendar_' + room.id); - cal.weekCalendar('option', 'data', {events: json}); - cal.weekCalendar("refresh"); - cal.weekCalendar("option", "defaultFreeBusy", {free: false}); - cal.weekCalendar("updateFreeBusy", room.openingTimesCalendar); + if (tmp[d]['HourClose'] >= close) { + close = tmp[d]['HourClose']; + if (tmp[d]['MinutesClose'] !== 0) { + close++; + } } - room.state = null; - UpdateRoomHeader(room); - } catch (e) { - console.log("Error: Couldnt add calendar data"); - console.log(e); } } - - /** - * scales calendar, called once on create and on window resize - * @param room Room Object - */ - function scaleCalendar(room) { - if (room.config.mode === 3) { - return; - } - 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 !== cal.weekCalendar("option", "daysToShow")) { - cal.weekCalendar("option", "daysToShow", result); + if (opening === 24 && close === 0) { + opening = 0; + close = 24; + } + room.openTimes = close - opening; + room.$.calendar.weekCalendar("option", "businessHours", { + start: opening, + end: close, + limitDisplay: true + }); + scaleCalendar(room); + } + + /** + * Filter out invalid opening time entries from given array, + * also make sure all the values are of type number (int) + * + * @param {Array} arr + * @return {Array} list of valid opening times + */ + function filterOpeningTimesDay(arr) { + if (!arr || arr.constructor !== Array) return []; + return arr.map(function (el) { + if (!el || typeof el !== 'object') return null; + for (var i = 0; i < OT_KEYS.length; ++i) { + el[OT_KEYS[i]] = toInt(el[OT_KEYS[i]]); + if (isNaN(el[OT_KEYS[i]])) return null; + } + return el; + }).filter(function (el) { + if (!el) return false; + if (el.HourOpen < 0 || el.HourOpen > 23) return false; + if (el.HourClose < 0 || el.HourClose > 23) return false; + if (el.HourClose < el.HourOpen) return false; + if (el.MinutesOpen < 0 || el.MinutesOpen > 59) return false; + if (el.MinutesClose < 0 || el.MinutesClose > 59) return false; + if (el.HourOpen === el.HourClose && el.MinutesClose < el.MinutesOpen) return false; + return true; + }); + } + + /** + * querys the Calendar data + */ + function queryCalendars() { + if (!panelUuid) return; + var url = "../../../api.php?do=locationinfo&get=calendar&uuid=" + panelUuid; + $.ajax({ + url: url, + dataType: 'json', + cache: false, + timeout: 30000, + success: function (result) { + if (result && result.constructor === Array) { + var l = result.length; + for (var i = 0; i < l; i++) { + updateCalendar(result[i].calendar, rooms[result[i].id]); + } } + }, error: function () { + // Retry in 5 minutes (300 seconds) + lastCalendarUpdate = MyDate().getTime() + globalConfig.calupdate + 300000; } - 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 (roomIds.length === 4) { - clientHeight = clientHeight / 2; - } - - clientHeight = clientHeight - document.getElementById('header_' + room.id).clientHeight - - document.getElementsByClassName("wc-time-column-header")[0].clientHeight - 2; - - if (room.config.mode === 1 && room.config.vertical) { - - clientHeight = clientHeight * (room.config.scale / 100); - clientHeight -= 22; - } - clientHeight -= 6; - var height = clientHeight / (room.openTimes * cal.weekCalendar("option", "timeslotsPerHour")); - - - if (height < 30) { - height = 30; - } - // Scale calendar font - if (height > 120) { - cal.weekCalendar("option", "textSize", 28); - } - else if (height > 100) { - cal.weekCalendar("option", "textSize", 24); - } else if (height > 80) { - cal.weekCalendar("option", "textSize", 22); - } else if (height > 70) { - cal.weekCalendar("option", "textSize", 20); - } else if (height > 60) { - cal.weekCalendar("option", "textSize", 14); - } else { - cal.weekCalendar("option", "textSize", 13); - } - cal.weekCalendar("option", "timeslotHeight", height); - if (room.timetable) { - cal.weekCalendar("option", "data", {events: room.timetable}); - cal.weekCalendar('refresh'); - } - if (room.openingTimesCalendar) { + }); + } + + const SEVEN_DAYS = 7 * 86400 * 1000; + + /** + * applays new calendar data to the calendar plugin and also saves it to the room object + * @param {Array} json Calendar data + * @param room Room Object + */ + function updateCalendar(json, room) { + if (!room) { + console.log("Error: No room for calendar data"); + return; + } + if (!json || json.constructor !== Array) { + console.log("Error: Calendar data was empty or malformed."); + return; + } + var now = MyDate().getTime(); + json = json.filter(function (el) { + if (!el.title || !el.start || !el.end) return false; + var s = new Date(el.start).getTime(); + var e = new Date(el.end).getTime(); + return !(isNaN(s) || isNaN(e) || Math.abs(s - now) > SEVEN_DAYS || Math.abs(e - now) > SEVEN_DAYS); + }); + if (json.length === 0) { + console.log('Notice: Calendar has no current events for ' + room.name); + } + try { + room.timetable = json; + if (room.config.mode !== 3) { + // TODO: Check if they're the same + var cal = room.$.calendar; + cal.weekCalendar('option', 'data', {events: json}); + cal.weekCalendar("refresh"); + cal.weekCalendar("option", "defaultFreeBusy", {free: false}); cal.weekCalendar("updateFreeBusy", room.openingTimesCalendar); } - cal.weekCalendar("resizeCalendar"); - cal.weekCalendar("scrollToHour"); - - } - - /** - * used for countdown - * computes the time difference between 2 Date objects - * @param {Date} a - * @param {Date} b - * @param room Room Object - * @returns time string - */ - function GetTimeDiferenceAsString(a, b, room) { - if (!a || !b) { - 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.eco) { - return hours + ":" + minutes; - } - return hours + ":" + minutes + ":" + seconds; - } - - /** - * returns next closing time of a given room - * @param room - * @returns Date Object of next closing - */ - function GetNextClosing(room) { - var now = MyDate(); - var day = now.getDay(); - var bestdate = false; - for (var a = 0; a < 7; a++) { - var tmp = room.openingTimes[(day + a) % 7]; - if (!tmp) continue; - for (var i = 0; i < tmp.length; i++) { - var closeDate = getNextDayOfWeek(now, (day + a) % 7); - closeDate.setHours(tmp[i].HourClose); - closeDate.setMinutes(tmp[i].MinutesClose); - closeDate.setSeconds(0); - if (closeDate > now) { - if (!IsOpen(new Date(closeDate.getTime() + 1800000), room)) { - if (!bestdate || bestdate > closeDate) { - bestdate = closeDate; - } + room.state = null; + UpdateRoomHeader(room); + } catch (e) { + console.log("Error: Couldnt add calendar data"); + console.log(e); + } + } + + /** + * scales calendar, called once on create and on window resize + * @param room Room Object + */ + function scaleCalendar(room) { + if (room.config.mode === 3) { + return; + } + var $cal = room.$.calendar; + if (!$cal.is(':visible')) return; + room.resizeCalendar = false; + var columnWidth = $cal.find(".wc-day-1").width(); + + 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 !== $cal.weekCalendar("option", "daysToShow")) { + $cal.weekCalendar("option", "daysToShow", 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 (roomIds.length === 4) { + clientHeight = clientHeight / 2; + } + + clientHeight = clientHeight - room.$.header.height() + - room.$.calendar.find(".wc-time-column-header").height() - 2; + + if (room.config.mode === 1 && room.config.vertical) { + + clientHeight = clientHeight * (room.config.scale / 100); + clientHeight -= 22; + } + clientHeight -= 6; + var height = clientHeight / (room.openTimes * $cal.weekCalendar("option", "timeslotsPerHour")); + + + if (height < 30) { + height = 30; + } + // Scale calendar font + if (height > 120) { + $cal.weekCalendar("option", "textSize", 28); + } + else if (height > 100) { + $cal.weekCalendar("option", "textSize", 24); + } else if (height > 80) { + $cal.weekCalendar("option", "textSize", 22); + } else if (height > 70) { + $cal.weekCalendar("option", "textSize", 20); + } else if (height > 60) { + $cal.weekCalendar("option", "textSize", 14); + } else { + $cal.weekCalendar("option", "textSize", 13); + } + $cal.weekCalendar("option", "timeslotHeight", height); + if (room.timetable) { + $cal.weekCalendar("option", "data", {events: room.timetable}); + $cal.weekCalendar('refresh'); + } + if (room.openingTimesCalendar) { + $cal.weekCalendar("updateFreeBusy", room.openingTimesCalendar); + } + $cal.weekCalendar("resizeCalendar"); + $cal.weekCalendar("scrollToHour"); + + } + + /** + * used for countdown + * computes the time difference between 2 Date objects + * @param {Date} a + * @param {Date} b + * @param room Room Object + * @returns time string + */ + function GetTimeDiferenceAsString(a, b, room) { + if (!a || !b) { + 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.eco) { + return hours + ":" + minutes; + } + return hours + ":" + minutes + ":" + seconds; + } + + /** + * returns next closing time of a given room + * @param room + * @returns Date Object of next closing + */ + function GetNextClosing(room) { + var now = MyDate(); + var day = now.getDay(); + var bestdate = false; + for (var a = 0; a < 7; a++) { + var tmp = room.openingTimes[(day + a) % 7]; + if (!tmp) continue; + for (var i = 0; i < tmp.length; i++) { + var closeDate = getNextDayOfWeek(now, (day + a) % 7); + closeDate.setHours(tmp[i].HourClose); + closeDate.setMinutes(tmp[i].MinutesClose); + closeDate.setSeconds(0); + if (closeDate > now) { + if (!IsOpen(new Date(closeDate.getTime() + 1800000), room)) { + if (!bestdate || bestdate > closeDate) { + bestdate = closeDate; } } } - if (bestdate) return bestdate; } - return null; + if (bestdate) return bestdate; + } + return null; + } + + + /** + * checks if a room is on a given date/time open + * @param date Date Object + * @param room Room object + * @returns bool for open or not + */ + function IsOpen(date, room) { + if (!room.openingTimes) return false; + var tmp = room.openingTimes[date.getDay()]; + if (!tmp) return false; + var openDate = new Date(date.getTime()); + var closeDate = new Date(date.getTime()); + for (var i = 0; i < tmp.length; i++) { + openDate.setHours(tmp[i].HourOpen); + openDate.setMinutes(tmp[i].MinutesOpen); + closeDate.setHours(tmp[i].HourClose); + closeDate.setMinutes(tmp[i].MinutesClose); + if (openDate < date && closeDate > date) { + return true; + } } + return false; + } - /** - * checks if a room is on a given date/time open - * @param date Date Object - * @param room Room object - * @returns bool for open or not - */ - function IsOpen(date, room) { - if (!room.openingTimes) return false; - var tmp = room.openingTimes[date.getDay()]; - if (!tmp) return false; - var openDate = new Date(date.getTime()); - var closeDate = new Date(date.getTime()); + /** + * Retruns next Opening + * @param room Room Object + * @returns bestdate Date Object of next opening + */ + function GetNextOpening(room) { + if (!room.openingTimes) return null; + var now = MyDate(); + var day = now.getDay(); + var bestdate = false; + for (var dow = 0; dow < 7; dow++) { + var tmp = room.openingTimes[(day + dow) % 7]; + if (!tmp) continue; for (var i = 0; i < tmp.length; i++) { + var openDate = getNextDayOfWeek(now, (day + dow) % 7); openDate.setHours(tmp[i].HourOpen); openDate.setMinutes(tmp[i].MinutesOpen); - closeDate.setHours(tmp[i].HourClose); - closeDate.setMinutes(tmp[i].MinutesClose); - if (openDate < date && closeDate > date) { - return true; - } - } - return false; - } - - - /** - * Retruns next Opening - * @param room Room Object - * @returns bestdate Date Object of next opening - */ - function GetNextOpening(room) { - if (!room.openingTimes) return null; - var now = MyDate(); - var day = now.getDay(); - var bestdate = false; - for (var dow = 0; dow < 7; dow++) { - var tmp = room.openingTimes[(day + dow) % 7]; - if (!tmp) continue; - for (var i = 0; i < tmp.length; i++) { - var openDate = getNextDayOfWeek(now, (day + dow) % 7); - openDate.setHours(tmp[i].HourOpen); - openDate.setMinutes(tmp[i].MinutesOpen); - if (openDate > now) { - if (!IsOpen(new Date(openDate.getTime() - 1800000), room)) { - if (!bestdate || bestdate > openDate) { - bestdate = openDate; - } + if (openDate > now) { + if (!IsOpen(new Date(openDate.getTime() - 1800000), room)) { + if (!bestdate || bestdate > openDate) { + bestdate = openDate; } } } - if (bestdate) return bestdate; } - return null; + if (bestdate) return bestdate; + } + return null; + } + + + /** + * Sets the free PCs number in the right corner and updates the sqare color acordingly + * @param room Room + * @param seats Number of free PC's in the room + */ + function SetFreeSeats(room, seats) { + room.$.seatsCounter.text(seats >= 0 ? seats : ''); + if (seats > 0) { + room.$.seatsBackground.css('background-color', '#00dd10'); + } else if (seats === -1) { + room.$.seatsBackground.css('background-color', 'red'); + } else { + room.$.seatsBackground.css('background-color', 'red'); + } + } + + /** + * Updates the Header of an Room + * @param room Room Object + */ + function UpdateRoomHeader(room) { + var tmp = room.getState(); + var same = (tmp === room.lastHeaderState); + if (!same) { + room.lastHeaderState = tmp; + } + var newText = false, newTime = false; + var seats = room.freePcs; + if (tmp.state === 'closed' || tmp.state === 'CalendarEvent' || tmp.state === 'Free') { + newTime = GetTimeDiferenceAsString(tmp.end, MyDate(), room); + } else if (!same) { + newTime = ''; + } + if (tmp.state === "closed") { + if (!same) newText = t("closed", globalConfig.language); + } else if (tmp.state === "CalendarEvent") { + if (!same) newText = tmp.title; + seats = -1; + } else if (tmp.state === "Free") { + if (!same) newText = t("free", room.config.language); + } else if (tmp.state === "FreeNoEnd") { + if (!same) newText = t("free", room.config.language); + } + if (newText !== false) { + room.$.currentEvent.text(newText); + } + if (newTime !== false) { + room.$.currentRemain.text(newTime); + } + if (room.lastFreeSeats !== seats) { + SetFreeSeats(room, room.freePcs); + room.lastFreeSeats = seats; + } + } + + /** + * computes state of a room, states are: + * closed, FreeNoEnd, Free, CalendarEvent. + * @param room Object + */ + function ComputeCurrentState(room) { + if (!IsOpen(MyDate(), 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 && !event) { + room.state = {state: "FreeNoEnd", end: "", title: "", next: ""}; + return; + } + + // no event so closing is next + if (!event) { + room.state = {state: "Free", end: closing, title: "", next: "closing"}; + return; + } + + // event is at the moment + if ((!closing || event.start.getTime() < closing.getTime()) && event.start.getTime() < MyDate()) { + room.state = { + state: "CalendarEvent", + end: event.end, + title: event.title, + next: "" + }; + return; } - - /** - * Sets the free PCs number in the right corner and updates the sqare color acordingly - * @param id Room id - * @param seats Number of free PC's in the 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'); - } + // no closing so event is next + if (!closing) { + room.state = {state: "Free", end: event.start, title: "", next: "event"}; + return; } - /** - * Updates the Header of an Room - * @param room Room Object - */ - function UpdateRoomHeader(room) { - var tmp = room.getState(); - if (tmp.state === "closed") { - $("#courseHeading_" + room.id).text(t("closed", room.config.language) + " " + GetTimeDiferenceAsString(tmp.end, MyDate(), room)); - SetFreeSeats(room.id, room.freePcs); - } else if (tmp.state === "CalendarEvent") { - $("#courseHeading_" + room.id).text(tmp.title); - SetFreeSeats(room.id, -1); - } else if (tmp.state === "Free") { - $("#courseHeading_" + room.id).text(t("free", room.config.language) + " " + GetTimeDiferenceAsString(tmp.end, MyDate(), room)); - SetFreeSeats(room.id, room.freePcs); - } else if (tmp.state === "FreeNoEnd") { - $("#courseHeading_" + room.id).text(t("free", room.config.language)); - SetFreeSeats(room.id, room.freePcs); - } + // event sooner then closing + if (event.start.getTime() < closing) { + room.state = {state: "Free", end: event.start, title: "", next: "event"}; + } else { + room.state = {state: "Free", end: closing, title: "", next: "closing"}; } - /** - * computes state of a room, states are: - * closed, FreeNoEnd, Free, CalendarEvent. - * @param room Object - */ - function ComputeCurrentState(room) { - if (!IsOpen(MyDate(), 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 && !event) { - room.state = {state: "FreeNoEnd", end: "", title: "", next: ""}; - return; + /** + * returns next event from a given json of events + * @param calEvents Json which contains the calendar data. + * @returns event next Carlendar Event + */ + function getNextEvent(calEvents) { + if (!calEvents) return null; + if (calEvents.constructor !== Array) { + console.log('getNextEvent called with something not array: ' + typeof(calEvents)); + return null; + } + var event; + var now = MyDate(); + for (var i = 0; i < calEvents.length; i++) { + //event is now active + if (calEvents[i].start.getTime() < now.getTime() && calEvents[i].end.getTime() > now.getTime()) { + return calEvents[i]; } - - // no event so closing is next + //first element to consider if (!event) { - room.state = {state: "Free", end: closing, title: "", next: "closing"}; - return; + if (calEvents[i].start.getTime() > now.getTime()) { + event = calEvents[i]; + } + } else if (calEvents[i].start.getTime() > now.getTime() && event.start.getTime() > calEvents[i].start.getTime()) { + event = calEvents[i]; } + } + return event; + } - // event is at the moment - if ((!closing || event.start.getTime() < closing.getTime()) && event.start.getTime() < MyDate()) { - room.state = {state: "CalendarEvent", end: event.end, title: event.title, next: ""}; - return; - } + /** + * Skip to next upcoming day matching the given day of week. + */ + function getNextDayOfWeek(date, dayOfWeek) { + var resultDate = new Date(date.getTime()); + resultDate.setDate(date.getDate() + (7 + dayOfWeek - date.getDay()) % 7); + return resultDate; + } + /* + /========================================== Room Layout ============================================= + */ - // no closing so event is next - if (!closing) { - 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 { - room.state = {state: "Free", end: closing, title: "", next: "closing"}; - } + var picSizeX = 3.8; + var picSizeY = 3; + /** + * Generates the RoomLayout Div + * @param width The width the RoomLayout should have (in percent). + * @param room Room Object + */ + function generateRoomLayoutDiv(width, room) { + if ((room.config.vertical && room.config.mode === 1) || (room.config.mode === 3) || (room.config.mode === 4)) { + width = 100 + "%"; } + var $div = $('<div>').prop('id', 'roomLayout_' + room.id).addClass("room-layout").css('width', width); + if (room.config.mode === 4) { + $div.hide(); + } + room.$.container.append($div); + room.$.layout = $div; + } - /** - * returns next event from a given json of events - * @param calEvents Json which contains the calendar data. - * @returns event next Carlendar Event - */ - function getNextEvent(calEvents) { - if (!calEvents) return null; - if (calEvents.constructor !== Array) { - console.log('getNextEvent called with something not array: ' + typeof(calEvents)); - return null; - } - var event; - var now = MyDate(); - for (var i = 0; i < calEvents.length; i++) { - //event is now active - if (calEvents[i].start.getTime() < now.getTime() && calEvents[i].end.getTime() > now.getTime()) { - return calEvents[i]; - } - //first element to consider - if (!event) { - if (calEvents[i].start.getTime() > now.getTime()) { - event = calEvents[i]; - } - } else if (calEvents[i].start.getTime() > now.getTime() && event.start.getTime() > calEvents[i].start.getTime()) { - event = calEvents[i]; - } - } - return event; - } - - /** - * Skip to next upcoming day matching the given day of week. - */ - function getNextDayOfWeek(date, dayOfWeek) { - 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; - - /** - * Generates the RoomLayout Div - * @param width The width the RoomLayout should have (in percent). - * @param room Room Object - */ - 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.style.width = width; - if (room.config.mode === 4) { - div.style.display = "none"; - } - //document.body.appendChild(div); - $("#room_" + room.id).append(div); - + /** + * Main function for generating the Room Layout + * @param room Room Object + */ + function initRoomLayout(room) { + var maxX = false, maxY = false; + var minX = false, minY = false; + var xDifference, yDifference; + var x, y; + generateRoomLayoutDiv((100 - room.config.scale) + "%", room); + var layout = room.layout; + if (layout === null || !layout.length) { + return; } - /** - * Main function for generating the Room Layout - * @param layout Layout Json - * @param room Room Object - */ - function initRoomLayout(room) { - var maxX = false, maxY = false; - var minX = false, minY = false; - var xDifference, yDifference; - var x, y; + rotateRoom(room.config.rotation, layout); - generateRoomLayoutDiv((100 - globalConfig.scale) + "%", room); - var layout = room.layout; - if (layout === null || !layout.length) { - return; + for (var i = 0; i < layout.length; i++) { + x = layout[i].x = parseInt(layout[i].x); + y = layout[i].y = parseInt(layout[i].y); + if (isNaN(x) || isNaN(y)) continue; + if (minX === false || x < minX) { + minX = x; } - - rotateRoom(globalConfig.rotation, layout); - - for (var i = 0; i < layout.length; i++) { - x = layout[i].x = parseInt(layout[i].x); - y = layout[i].y = parseInt(layout[i].y); - if (isNaN(x) || isNaN(y)) continue; - if (minX === false || x < minX) { - minX = x; - } - if (minY === false || y < minY) { - minY = y; - } - if (maxX === false || x > maxX) { - maxX = x; - } - if (maxY === false || y > maxY) { - maxY = y; - } + if (minY === false || y < minY) { + minY = y; + } + if (maxX === false || x > maxX) { + maxX = x; + } + if (maxY === false || y > maxY) { + maxY = 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); - } - /** - * Computes offsets and scaling's for the RoomLayout - * @param room Room Object - */ - function generateOffsetAndScale(room) { + xDifference = maxX - minX; + yDifference = maxY - minY; - var clientHeight = $(window).height(); - if (roomIds.length === 4) { - clientHeight = clientHeight / 2; - } + room.xDifference = xDifference; + room.yDifference = yDifference; + room.minX = minX; + room.minY = minY; + room.maxX = maxX; + room.maxY = maxY; - clientHeight = clientHeight - document.getElementById('header_' + room.id).clientHeight - 5; + setUpRoom(room, layout); + scaleRoom(room); + UpdatePc(layout, room); - if (roomIds.length > 1) { - clientHeight -= 5; - } - if (globalConfig.vertical && globalConfig.mode === 1) { - clientHeight = clientHeight * (1 - (globalConfig.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; - } + /** + * Computes offsets and scaling's for the RoomLayout + * @param room Room Object + */ + function generateOffsetAndScale(room) { - room.scale = Math.min(scaleYs, scaleY, scaleXs, scaleX, (clientHeight * 0.9) / picSizeY, (clientWidth * 0.9) / picSizeX); - 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); + var clientHeight = $(window).height(); + if (roomIds.length === 4) { + clientHeight /= 2; } - - /** - * adds images for each pc to Room Layout - * @param room Room Object - * @param layout Layout json - */ - function setUpRoom(room, layout) { - for (var i = 0; i < layout.length; i++) { - if (!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].overlay && layout[i].overlay.constructor === Array) { - for (var a = 0; a < layout[i].overlay.length; a++) { - addOverlay($('#layout_PC_overlay_' + room.id + "_" + layout[i].id), layout[i].overlay[a]); - } - } - } - } + clientHeight -= room.$.header.height() - 5; + + if (roomIds.length > 1) { + clientHeight -= 5; + } + if (room.config.vertical && room.config.mode === 1) { + clientHeight *= (1 - (room.config.scale / 100)); } - /** - * Adds an overlay to an div(here the PC's shown in the RoomLayout). - * @param object Object where the overlay should be added - * @param overlayName name of the overlay (image name without ending) - */ - 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; - } + var clientWidth = room.$.layout.width(); - } - if (!imgname) return; // No image found on server, do nothing - var $text = $("<img>"); - $text.addClass('overlay').attr('src', imgname).addClass("overlay-" + overlayName); - object.append($text); + 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; } + room.scale = Math.min(scaleYs, scaleY, scaleXs, scaleX, (clientHeight * 0.9) / picSizeY, (clientWidth * 0.9) / picSizeX); + 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); + } - var imgExists = {}; - /** - * checks if images exists on the webserver(chaches it also) - * @param image_url Path to the image - */ - 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 === 200; - } - return imgExists[image_url]; - - } - - /** - * Querys Pc states - */ - function queryRooms() { - $.ajax({ - url: "../../../api.php?do=locationinfo&get=machines&uuid=" + panelUuid, - dataType: 'json', - cache: false, - timeout: 30000, - success: function (result) { - if (!result || result.constructor !== Array) { - console.log('Warning: get=machines didnt return array'); - return; - } - for (var i = 0; i < result.length; i++) { - UpdatePc(result[i].machines, rooms[result[i].id]); - } - } - }) - } - - /** - * Updates the PC's (images) in the room layout. Also Updates how many pc's are free. - * @param update Update Json from query for one(!) room - * @param room Room object - */ - function UpdatePc(update, room) { - if (!room) { - console.log('Got room update for unknown room, ignored.'); - return; - } - if (!update || update.constructor !== Array) { - console.log('Update data is not array for room ' + room.name); - console.log(update); - return; - } - var freePcs = 0; - for (var i = 0; i < update.length; i++) { - var $imgobj = $("#layout_PC_" + room.id + "_" + update[i].id); - - var img; - var color; - // Pc free - if (update[i].pcState === "IDLE") { - img = "img/pc_free"; - color = 'green'; - freePcs++; - // Pc in use - } else if (update[i].pcState === "OCCUPIED") { - img = "img/pc_used"; - color = 'red'; - // PC off - } else if (update[i].pcState === "OFF") { - img = "img/pc_off"; - color = 'black'; - freePcs++; - // Must be defect - } else { - img = "img/pc_defect"; - color = 'black'; - } + /** + * adds images for each pc to Room Layout + * @param room Room Object + * @param layout Layout json + */ + function setUpRoom(room, layout) { + for (var i = 0; i < layout.length; i++) { + if (!isNaN(layout[i].y) && !isNaN(layout[i].x)) { + var $img = $('<img>').prop('id', "pc-img_" + room.id + "_" + layout[i].id).addClass('pc-img'); + var $overlays = $('<div>').addClass('pc-overlay-container'); + layout[i].$div = $('<div>').addClass('pc-container'); + layout[i].$div.append($overlays).append($img); + room.$.layout.append(layout[i].$div); - if (supportSvg) { - if (room.config.eco) { - img = img + "_eink"; + if (layout[i].overlay && layout[i].overlay.constructor === Array) { + for (var a = 0; a < layout[i].overlay.length; a++) { + addOverlay($overlays, layout[i].overlay[a]); } - $imgobj.attr('src', img + ".svg"); - } else { - $imgobj.css('background-color', color); } - } - room.freePcs = freePcs; - UpdateRoomHeader(room); } - - /** - * Adjust pc coordinate depending on room rotation - * @param r Rotation, from 0 - 3 (int) - * @param layout Layout json - */ - 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; + } + + /** + * Generate overlay with given image name. + * @param $container container to put overlay into + * @param overlayName name of the overlay (image name without ending) + */ + function addOverlay($container, 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) return null; // No image found on server, do nothing + var $overlay = $("<img>"); + $overlay.addClass('overlay').attr('src', imgname).addClass("overlay-" + overlayName); + $container.append($overlay); + } + + + var imgExists = {}; + + /** + * checks if images exists on the web server. + * result will be cached after fist call. + * + * @param {String} image_url URL of image to check + * @return {Boolean} true iff image exists + */ + 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 === 200; + } + return imgExists[image_url]; + + } + + /** + * Queries Pc states + */ + function queryRooms() { + $.ajax({ + url: "../../../api.php?do=locationinfo&get=machines&uuid=" + panelUuid, + dataType: 'json', + cache: false, + timeout: 30000, + success: function (result) { + if (!result || result.constructor !== Array) { + console.log('Warning: get=machines didnt return array'); + return; } - } - } - - /** - * Positions the computer images in the roomLayout div accoring to ther potion and div size - * @param room Room object - */ - function scaleRoom(room) { - for (var i = 0; i < room.layout.length; i++) { - if (!isNaN(room.layout[i].y) && !isNaN(room.layout[i].x)) { - var tmp = document.getElementById("layout_PC_div_" + room.id + "_" + room.layout[i].id); - if (tmp) { - tmp.style.width = (picSizeX * room.scale); - tmp.setAttribute("style", "width:" + (picSizeX * room.scale) + "px"); - tmp.style.height = (picSizeY * room.scale) + "px"; - tmp.style.left = ((room.layout[i].x + room.xOffset) * room.scale) + "px"; - tmp.style.top = ((room.layout[i].y + room.yOffset) * room.scale) + "px"; - } + for (var i = 0; i < result.length; i++) { + UpdatePc(result[i].machines, rooms[result[i].id]); } } - } - - /* - /========================================== Misc ============================================= - */ - var resizeTimeout = false; - - // called when browser window changes size - // scales calendar and room layout acordingly - - $(window).resize(function () { - if (resizeTimeout) clearTimeout(resizeTimeout); - resizeTimeout = setTimeout(function () { - resizeTimeout = false; - 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]); - } - } - } - SetProgressBarSpeed(); - }, 200); - }); - - - /** - * returns parameter value from the url - * @param sParam - * @returns value for given parameter - */ - 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('=', 2); - - if (sParameterName[0] === sParam) { - if (sParameterName.length === 1) return true; - return sParameterName[1]; - } + }) + } + + /** + * Updates the PC's (images) in the room layout. Also Updates how many pc's are free. + * @param update Update Json from query for one(!) room + * @param room Room object + */ + function UpdatePc(update, room) { + if (!room) { + console.log('Got room update for unknown room, ignored.'); + return; + } + if (!update || update.constructor !== Array) { + console.log('Update data is not array for room ' + room.name); + console.log(update); + return; + } + var freePcs = 0; + for (var i = 0; i < update.length; i++) { + var $imgobj = $("#pc-img_" + room.id + "_" + update[i].id); + + var img; + var color; + // Pc free + if (update[i].pcState === "IDLE") { + img = "img/pc_free"; + color = 'green'; + freePcs++; + // Pc in use + } else if (update[i].pcState === "OCCUPIED") { + img = "img/pc_used"; + color = 'red'; + // PC off + } else if (update[i].pcState === "OFF") { + img = "img/pc_off"; + color = 'black'; + freePcs++; + // Must be defect + } else { + img = "img/pc_defect"; + color = 'black'; } - return false; - }; - /** - * Function for translation - * @param toTranslate key which we wan't to translate - * @param lang languages in which should be translated - * @returns r translated string - */ - function t(toTranslate, lang) { - - var r; - if (!lang || !translation[lang] || !translation[lang][toTranslate]) { - r = translation['en'][toTranslate] || 'missing'; + if (supportSvg) { + if (globalConfig.eco) { + img = img + "_eink"; + } + $imgobj.attr('src', img + ".svg"); } else { - r = translation[lang][toTranslate]; + $imgobj.css('background-color', color); } - return r; - } - - - /** - * Used in Mode 4, switches given room from Timetable to Roomlayout and vice versa - * @param room - */ - function switchLayouts() { - for (var roomKey in rooms) { - var room = rooms[roomKey]; - if (room.config.mode !== 4) continue; - 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; - } - } + + } + room.freePcs = freePcs; + UpdateRoomHeader(room); + } + + /** + * Adjust pc coordinate depending on room rotation + * @param r Rotation, from 0 - 3 (int) + * @param layout Layout json + */ + 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 according to their position and div size + * @param room Room object + */ + function scaleRoom(room) { + if (!room.$.layout.is(':visible')) return; + room.resizeRoom = false; + generateOffsetAndScale(room); + for (var i = 0; i < room.layout.length; i++) { + var pcWidth = (picSizeX * room.scale) + "px"; + var pcHeight = (picSizeY * room.scale) + "px"; + if (room.layout[i].$div && !isNaN(room.layout[i].y) && !isNaN(room.layout[i].x)) { + room.layout[i].$div.css({ + width: pcWidth, + height: pcHeight, + top: ((room.layout[i].y + room.yOffset) * room.scale) + "px", + left: ((room.layout[i].x + room.xOffset) * room.scale) + "px" + }); } - lastSwitchTime = MyDate().getTime(); } + } - var $pbar = false; - var pbarTimer = false; - const PX_PER_SEC_TARGET = 10; + /* + /========================================== Misc ============================================= + */ + var resizeTimeout = false; - /** - * adds a progressbar (id) used in mode 4 - */ - function generateProgressBar() { - if ($pbar) return; - $pbar = $('<div id="progressBar" class="progressbar">'); - $('body').append($pbar); - SetProgressBarSpeed() - } + // called when browser window changes size + // scales calendar and room layout accordingly - function SetProgressBarSpeed() { - if (!$pbar || !globalConfig.switchtime) return; - if (pbarTimer) clearInterval(pbarTimer); - var pxPerMSec = $('body').width() / globalConfig.switchtime; - var interval = Math.max(1 / (pxPerMSec / PX_PER_SEC_TARGET), 100); - pbarTimer = setInterval(function () { - var width = ((MyDate().getTime() - lastSwitchTime) / globalConfig.switchtime) * 100; - if (width < 0) width = 0; - if (width >= 100) { - width = 100; - switchLayouts(); - } - $pbar.width(width + '%'); - }, interval); + $(window).resize(function () { + if (resizeTimeout !== false) clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(function () { + resizeTimeout = false; + for (var property in rooms) { + rooms[property].resizeCalendar = true; + rooms[property].resizeRoom = true; + scaleCalendar(rooms[property]); + scaleRoom(rooms[property]); + } + SetProgressBarSpeed(); + }, 200); + }); + + + /** + * returns parameter value from the url + * @param sParam + * @returns boolean|string for given parameter + */ + 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('=', 2); + + if (sParameterName[0] === sParam) { + if (sParameterName.length === 1) return true; + return sParameterName[1]; + } + } + return false; + } + + /** + * Function for translation + * @param toTranslate key which we wan't to translate + * @param lang languages in which should be translated + * @returns r translated string + */ + function t(toTranslate, lang) { + + var r; + if (!lang || !translation[lang] || !translation[lang][toTranslate]) { + r = translation['en'][toTranslate] || 'missing'; + } else { + r = translation[lang][toTranslate]; + } + return r; + } + + function resizeIfRequired(room) { + if (room.resizeCalendar) { + scaleCalendar(room); } - - function toInt(str) { - var t = typeof str; - if (t === 'number') return str | 0; - if (t === 'string') return parseInt(str.replace(/^0+([^0])/, '$1')); - return NaN; + if (room.resizeRoom) { + scaleRoom(room); } + } - </script> -</head> -<body> -</body> + + /** + * Used in Mode 4, switches given room from Timetable to room layout and vice versa + */ + function switchLayouts() { + for (var roomKey in rooms) { + var room = rooms[roomKey]; + if (room.config.mode !== 4) continue; + if (room.$.layout.is(':visible')) { + room.$.layout.hide(); + room.$.calendar.show(); + } else { + room.$.layout.show(); + room.$.calendar.hide(); + } + resizeIfRequired(room); + } + lastSwitchTime = MyDate().getTime(); + } + + var $pbar = false; + var pbarTimer = false; + const PX_PER_SEC_TARGET = 10; + + /** + * adds a progressbar (id) used in mode 4 + */ + function generateProgressBar() { + if ($pbar) return; + $pbar = $('<div id="progressBar" class="progressbar">'); + $('body').append($pbar); + SetProgressBarSpeed(); + } + + function SetProgressBarSpeed() { + if (!$pbar || !globalConfig.switchtime) return; + if (pbarTimer) clearInterval(pbarTimer); + var interval = 1000; + if (!globalConfig.eco) { + var pxPerMSec = $('body').width() / globalConfig.switchtime; + interval = Math.max(1 / (pxPerMSec / PX_PER_SEC_TARGET), 100); + } + pbarTimer = setInterval(function () { + var width = ((MyDate().getTime() - lastSwitchTime) / globalConfig.switchtime) * 100; + if (width < 0) width = 0; + if (width >= 100) { + width = 100; + switchLayouts(); + } + $pbar.width(width + '%'); + }, interval); + } + + function toInt(str) { + var t = typeof str; + if (t === 'number') return str | 0; + if (t === 'string') return parseInt(str.replace(/^0+([^0])/, '$1')); + return NaN; + } + +</script> </html> |