New door-graph, Improved slideshow, moved video
This commit is contained in:
parent
a4ce890a36
commit
6c891b3f79
|
@ -157,11 +157,10 @@ nav #usermenu li:first-child:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 8px 8px;
|
padding: 8px 8px;
|
||||||
margin: 4px 4px;
|
margin: 4px 4px;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
#doorIndicator > p > abbr[title] { text-decoration: none; border-bottom: none; cursor: inherit; }
|
|
||||||
.doorIndicator_OPEN { border: 2px solid green; }
|
.doorIndicator_OPEN { border: 2px solid green; }
|
||||||
.doorIndicator_CLOSED { border: 2px dotted red; }
|
.doorIndicator_CLOSED { border: 2px dotted red; }
|
||||||
.doorStateMobileOnly { display: none; }
|
|
||||||
|
|
||||||
#mazeMapper {
|
#mazeMapper {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,8 @@
|
||||||
|
/*!
|
||||||
|
* chartjs-adapter-moment v1.0.0
|
||||||
|
* https://www.chartjs.org
|
||||||
|
* (c) 2021 chartjs-adapter-moment Contributors
|
||||||
|
* Released under the MIT license
|
||||||
|
*/
|
||||||
|
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("moment"),require("chart.js")):"function"==typeof define&&define.amd?define(["moment","chart.js"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).moment,e.Chart)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=n(e);const a={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};t._adapters._date.override("function"==typeof f.default?{_id:"moment",formats:function(){return a},parse:function(e,t){return"string"==typeof e&&"string"==typeof t?e=f.default(e,t):e instanceof f.default||(e=f.default(e)),e.isValid()?e.valueOf():null},format:function(e,t){return f.default(e).format(t)},add:function(e,t,n){return f.default(e).add(t,n).valueOf()},diff:function(e,t,n){return f.default(e).diff(f.default(t),n)},startOf:function(e,t,n){return e=f.default(e),"isoWeek"===t?(n=Math.trunc(Math.min(Math.max(0,n),6)),e.isoWeekday(n).startOf("day").valueOf()):e.startOf(t).valueOf()},endOf:function(e,t){return f.default(e).endOf(t).valueOf()}}:{})}));
|
||||||
|
//# sourceMappingURL=chartjs-adapter-moment.min.js.map
|
|
@ -5,20 +5,38 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Inngangsverkstedet</title>
|
<title>Inngangsverkstedet</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
width: 80vw;
|
||||||
|
margin: auto auto;
|
||||||
|
}
|
||||||
|
#graphDiv {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Felixalb 2021 -->
|
|
||||||
<h2>En kort analyse av nerders døgnrytme i deres naturlige habitat, PVV</h2>
|
<h2>En kort analyse av nerders døgnrytme i deres naturlige habitat, PVV</h2>
|
||||||
<h3 id="infoText"></h3>
|
<div id="graphDiv">
|
||||||
<canvas id="doorGraph1"></canvas>
|
<h4>Siste 24 timer</h4>
|
||||||
<script src="./p5.min.js"></script>
|
<canvas id="doorGraphDay"></canvas>
|
||||||
|
<h4>Siste 7 dager</h4>
|
||||||
|
<canvas id="doorGraphWeek"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="chart.min.js"></script>
|
||||||
|
<script src="moment.js"></script>
|
||||||
|
<script src="chartjs-adapter-moment.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const infoEl = document.getElementById("infoText");
|
const graphElDay = document.getElementById("doorGraphDay");
|
||||||
const graphEl1 = document.getElementById("doorGraph1");
|
const graphElWeek = document.getElementById("doorGraphWeek");
|
||||||
|
|
||||||
const XHR = new XMLHttpRequest();
|
const XHR = new XMLHttpRequest();
|
||||||
const url="/door/?period=day&edgeonly=true";
|
const url="/door/?period=week";
|
||||||
XHR.open("GET", url);
|
XHR.open("GET", url);
|
||||||
XHR.send();
|
XHR.send();
|
||||||
|
|
||||||
|
@ -26,76 +44,102 @@
|
||||||
XHR.onreadystatechange = ()=>{
|
XHR.onreadystatechange = ()=>{
|
||||||
if (XHR.readyState == 4 && XHR.status == 200) {
|
if (XHR.readyState == 4 && XHR.status == 200) {
|
||||||
console.log("Response 200 from API")
|
console.log("Response 200 from API")
|
||||||
response = JSON.parse(XHR.responseText);
|
response = JSON.parse(XHR.responseText); //Should be try-catched?
|
||||||
if (response.status != "OK") {
|
if (response.status != "OK") {
|
||||||
infoEl.innerHTML = "Error when connecting to API.";
|
console.log("Error when connecting to API.");
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
let datapoints = response.entries;
|
const allDatapoints = response.entries;
|
||||||
console.log("Success, " + datapoints.length + " datapoints received.");
|
console.log("Success, " + allDatapoints.length + " datapoints received.");
|
||||||
// displayLineDiagram(graphEl1, datapoints);
|
|
||||||
displayBar(datapoints);
|
const dayDatapoints = getLastDay(allDatapoints);
|
||||||
|
|
||||||
|
displayLineDiagram(graphElDay, dayDatapoints, "hour");
|
||||||
|
displayLineDiagram(graphElWeek, allDatapoints, "day");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getDateString(time) {
|
function getLastDay(data) {
|
||||||
// let dateObj = new Date(time*1e3);
|
let date = new Date();
|
||||||
// return dateObj.toLocaleString();
|
let curTime = date.getTime();
|
||||||
// }
|
let targetTime = parseInt(curTime/1e3) - (60*60*24);
|
||||||
|
|
||||||
// function displayLineDiagram(canv, data) {
|
let i;
|
||||||
// let ctx = canv.getContext("2d");
|
for (i = 0; i < data.length; i++) {
|
||||||
// let chart = new Chart(ctx, {
|
if (data[i].time < targetTime) {
|
||||||
// type: 'line',
|
break;
|
||||||
// data: {
|
}
|
||||||
// labels: data.map(entry=> getDateString(entry.time)),
|
}
|
||||||
// // labels: data.map(entry=> 1e3 * entry.time),
|
return data.slice(0, i);
|
||||||
// datasets: [{
|
|
||||||
// data: data.map(entry => entry.open)
|
|
||||||
// }],
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
createCanvas(800, 200);
|
|
||||||
noLoop();
|
|
||||||
background(50);
|
|
||||||
}
|
}
|
||||||
function draw() {}
|
|
||||||
function displayBar(data) {
|
|
||||||
const fullLength = 60*60*24;
|
|
||||||
// const dateObj = new Date();
|
|
||||||
const curTime = Math.floor(Date.now() / 1000)
|
|
||||||
let borderPositions = [0];
|
|
||||||
|
|
||||||
//Convert timestamps to a position on the graph
|
|
||||||
for(let i = data.length-1; i > 0; i--) {
|
|
||||||
const ts = data[i]["time"];
|
|
||||||
const pixelPos = width - (((curTime - ts) / fullLength) * width);
|
|
||||||
borderPositions.push(pixelPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(borderPositions);
|
function displayLineDiagram(canv, data, timeunit) {
|
||||||
|
let ctx = canv.getContext("2d");
|
||||||
|
let dotColor = data.map(entry => entry.open ? "rgb(10, 150, 10)" : "rgb(200, 100, 100)");
|
||||||
|
|
||||||
let sectionColors = ["gray"];
|
let chart = new Chart(ctx, {
|
||||||
//Define list of colors, gray=?, green=open, red=closed
|
type: 'line',
|
||||||
for(let i = 0; i < data.length; i++) {
|
data: {
|
||||||
sectionColors.push((data[i]["open"]) ? "green" : "red");
|
labels: data.map(entry=> 1e3 * entry.time),
|
||||||
}
|
datasets: [{
|
||||||
console.log(sectionColors);
|
data: data.map(entry => entry.open),
|
||||||
for(let i = 0; i < borderPositions.length-1; i++) {
|
stepped: "before",
|
||||||
fill(sectionColors[i]);
|
borderColor: dotColor,
|
||||||
rect(borderPositions[i], 0, borderPositions[i+1], height);
|
backgroundColor: dotColor
|
||||||
console.log(`${sectionColors[i]} from ${borderPositions[i]}px to ${borderPositions[i+1]}px`)
|
}],
|
||||||
}
|
},
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
xAxis: {
|
||||||
|
type: "time",
|
||||||
|
time: {
|
||||||
|
unit: timeunit
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
suggestedMin: -0.1,
|
||||||
|
suggestedMax: 1.1,
|
||||||
|
grid: {display: false},
|
||||||
|
ticks: {
|
||||||
|
callback: function(label, index, labels) {
|
||||||
|
if (label == 0) {
|
||||||
|
return "Stengt";
|
||||||
|
} else if (label == 1) {
|
||||||
|
return "Åpent";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(tooltipItem) {
|
||||||
|
const value = tooltipItem.formattedValue;
|
||||||
|
if (value == 0) {
|
||||||
|
return "Stengt";
|
||||||
|
} else if (value == 1) {
|
||||||
|
return "Åpent";
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <script src="./chart.min.js"></script> -->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -38,7 +38,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
}
|
}
|
||||||
|
|
||||||
$lines = $door->getEntriesAfter($startTime);
|
$lines = $door->getEntriesAfter($startTime);
|
||||||
if (isset($_GET["period"]) && (bool)htmlspecialchars($_GET["edgeonly"])) {
|
if (isset($_GET["edgeonly"]) && (bool)htmlspecialchars($_GET["edgeonly"])) {
|
||||||
//Ignore repeats
|
//Ignore repeats
|
||||||
$lines = getChanges($lines);
|
$lines = getChanges($lines);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,32 @@
|
||||||
|
const SLIDESHOWDELAYMS = 3500;
|
||||||
|
|
||||||
|
//Defined in slideshow.php: const slideshowFnames
|
||||||
|
|
||||||
|
let slideshowIndex = 1;
|
||||||
|
let slideshowInterval;
|
||||||
|
|
||||||
|
let ssi1 = document.getElementById("slideshowImage1");
|
||||||
|
let ssi2 = document.getElementById("slideshowImage2");
|
||||||
|
|
||||||
|
|
||||||
|
function stepSlideshow(imgs) {
|
||||||
|
//Swap image elements
|
||||||
|
let tmp = ssi1;
|
||||||
|
ssi1 = ssi2;
|
||||||
|
ssi2 = tmp;
|
||||||
|
//Swap visibility
|
||||||
|
ssi2.classList.remove("slideshowactive");
|
||||||
|
ssi1.classList.add("slideshowactive");
|
||||||
|
setTimeout(()=>{
|
||||||
|
//Change source to next picture after it is faded out
|
||||||
|
slideshowIndex = (slideshowIndex + 1) % imgs.length;
|
||||||
|
ssi2.src = slideshowFnames[slideshowIndex];
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize slideshow, start interval
|
||||||
|
if (slideshowFnames.length > 1) {
|
||||||
|
slideshowInterval = setInterval(()=>{
|
||||||
|
stepSlideshow(slideshowFnames);
|
||||||
|
}, SLIDESHOWDELAYMS);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
//Short path to search folder, full to display in <img>
|
||||||
|
$relativePath = "/bilder/slideshow/";
|
||||||
|
$absolutePath = "/galleri" . $relativePath;
|
||||||
|
//Path to first image in slideshow and fallback image if no others are present
|
||||||
|
$splashImg = "/PNG/PVV-logo-big-bluebg.png";
|
||||||
|
|
||||||
|
$filenames = sCaNdIr(__DIR__ . $relativePath);
|
||||||
|
|
||||||
|
//Remove the expected non-images
|
||||||
|
foreach($filenames as $k => $value) {
|
||||||
|
if(in_array($value, [".gitkeep", ".", ".."])) {
|
||||||
|
unset($filenames[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFullPath($fname) { return ($GLOBALS["absolutePath"] . $fname ); }
|
||||||
|
|
||||||
|
//Sort filenames alphabetically and prepend the path prefix to each item.
|
||||||
|
asort($filenames);
|
||||||
|
$slideshowimagefilenames = aRrAy_MaP("getFullPath", $filenames);
|
||||||
|
|
||||||
|
//Prepend the cover photo
|
||||||
|
ArRaY_uNsHiFt($slideshowimagefilenames, $splashImg);
|
||||||
|
|
||||||
|
eChO('<img class="slideshowimg slideshowactive" id="slideshowImage1" src="' . $slideshowimagefilenames[0] . '">');
|
||||||
|
ecHo('<img class="slideshowimg" id="slideshowImage2" src="' . $slideshowimagefilenames[1] . '">');
|
||||||
|
//Store list of file names in a globel JS variable
|
||||||
|
EchO("<script> const slideshowFnames =" . jSoN_eNcOdE($slideshowimagefilenames) . "; </script>");
|
||||||
|
?>
|
107
www/index.php
107
www/index.php
|
@ -10,9 +10,13 @@ $motd = $motdfetcher->getMOTD();
|
||||||
|
|
||||||
$door = new \pvv\side\Door($pdo);
|
$door = new \pvv\side\Door($pdo);
|
||||||
$doorEntry = (object)($door->getCurrent());
|
$doorEntry = (object)($door->getCurrent());
|
||||||
$isDoorOpen = $doorEntry->open;
|
if ($doorEntry->time < (time() - 60*30)) {
|
||||||
if (date("Y-m-d") == date("Y-m-d", $doorEntry->time)) { $doorTime = date("H:i", $doorEntry->time);
|
$doorStateText = "Ingen data fra dørsensor";
|
||||||
} else { $doorTime = date("H:i d/m", $doorEntry->time);}
|
} else {
|
||||||
|
if ($doorEntry->open) { $doorStateText = "Døren er <b>åpen</b>";
|
||||||
|
} else { $doorStateText = "Døren er <b>ikke åpen</b>"; }
|
||||||
|
}
|
||||||
|
$doorTime = date("H:i", $doorEntry->time);
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="no">
|
<html lang="no">
|
||||||
|
@ -36,96 +40,9 @@ if (date("Y-m-d") == date("Y-m-d", $doorEntry->time)) { $doorTime = date("H:i",
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<header class="landing">
|
<header class="landing">
|
||||||
<!-- Statisk bilde:
|
|
||||||
<img class="logo" src="css/logo-white.png"/>
|
|
||||||
-->
|
|
||||||
<!-- Youtube-iframe:
|
|
||||||
<style>
|
|
||||||
.iframe-container {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then style the iframe to fit in the container div with full height and width */
|
|
||||||
.responsive-iframe {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div class="iframe-container" style="max-width: 100em;">
|
|
||||||
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/l-iEkaQNQdk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div id="imageSlideshow">
|
<div id="imageSlideshow">
|
||||||
<?php
|
<?php include("galleri/slideshow.php"); ?>
|
||||||
|
<script src="galleri/slideshow.js"></script>
|
||||||
$path = "/galleri/bilder/slideshow/";
|
|
||||||
$splashImg = "/PNG/PVV-logo-big-bluebg.png";
|
|
||||||
|
|
||||||
//Find all files/dirs in folder and discard . and .. directories
|
|
||||||
$filenames = aRrAy_SlIcE(sCaNdIr(__DIR__ . $path), 2);
|
|
||||||
|
|
||||||
function getFullPath($fname) { return ($GLOBALS["path"] . $fname ); }
|
|
||||||
|
|
||||||
//Sort filenames alphabetically and prepend the path prefix to each item.
|
|
||||||
asort($filenames);
|
|
||||||
$slideshowimagefilenames = aRrAy_MaP("getFullPath", $filenames);
|
|
||||||
|
|
||||||
//Prepend the cover photo
|
|
||||||
ArRaY_uNsHiFt($slideshowimagefilenames, $splashImg);
|
|
||||||
|
|
||||||
eChO('<img class="slideshowimg slideshowactive" id="slideshowImage1" src="' . $slideshowimagefilenames[0] . '">');
|
|
||||||
ecHo('<img class="slideshowimg" id="slideshowImage2" src="' . $slideshowimagefilenames[1] . '">');
|
|
||||||
|
|
||||||
//Store list of file names in a globel JS variable
|
|
||||||
EchO("<script> const slideshowFnames =" . jSoN_eNcOdE($slideshowimagefilenames) . "; </script>");
|
|
||||||
?>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const SLIDESHOWDELAYMS = 3500; //Minimum 3 * fade time (3*800=2400ms)
|
|
||||||
|
|
||||||
let slideshowIndex = 1;
|
|
||||||
let slideshowInterval;
|
|
||||||
|
|
||||||
const ssi1 = document.getElementById("slideshowImage1");
|
|
||||||
const ssi2 = document.getElementById("slideshowImage2");
|
|
||||||
|
|
||||||
function stepSlideshow(imgs) {
|
|
||||||
//Change visible picture, ssi2 active, fades with css
|
|
||||||
ssi1.classList.remove("slideshowactive");
|
|
||||||
ssi2.classList.add("slideshowactive");
|
|
||||||
|
|
||||||
setTimeout(()=>{
|
|
||||||
//Change to ssi1 active, no visible change
|
|
||||||
ssi1.src = ssi2.src;
|
|
||||||
ssi1.classList.add("slideshowactive");
|
|
||||||
|
|
||||||
// Hide ssi2 after ssi1 has appeared, no visible change
|
|
||||||
setTimeout(()=>{
|
|
||||||
ssi2.classList.remove("slideshowactive");
|
|
||||||
}, 800);
|
|
||||||
|
|
||||||
//Prepare for next cycle, no visible change
|
|
||||||
setTimeout(()=>{
|
|
||||||
slideshowIndex = (slideshowIndex + 1) % imgs.length;
|
|
||||||
ssi2.src = imgs[slideshowIndex];
|
|
||||||
}, 1600);
|
|
||||||
}, 800);
|
|
||||||
}
|
|
||||||
//Initialize slideshow, start interval
|
|
||||||
if (slideshowFnames.length > 1) {
|
|
||||||
slideshowInterval = setInterval(()=>{
|
|
||||||
stepSlideshow(slideshowFnames);
|
|
||||||
}, SLIDESHOWDELAYMS);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
|
@ -136,9 +53,9 @@ if (date("Y-m-d") == date("Y-m-d", $doorEntry->time)) { $doorTime = date("H:i",
|
||||||
<a class="btn" href="om/"><li>Om PVV</li></a>
|
<a class="btn" href="om/"><li>Om PVV</li></a>
|
||||||
<a class="btn focus" href="paamelding/"><li>Bli medlem!</li></a>
|
<a class="btn focus" href="paamelding/"><li>Bli medlem!</li></a>
|
||||||
<a class="btn" href="https://use.mazemap.com/#config=ntnu&v=1&zlevel=2¢er=10.406281,63.417093&zoom=19.5&campuses=ntnu&campusid=1&sharepoitype=poi&sharepoi=38159&utm_medium=longurl">Veibeskrivelse</li></a>
|
<a class="btn" href="https://use.mazemap.com/#config=ntnu&v=1&zlevel=2¢er=10.406281,63.417093&zoom=19.5&campuses=ntnu&campusid=1&sharepoitype=poi&sharepoi=38159&utm_medium=longurl">Veibeskrivelse</li></a>
|
||||||
<div id="doorIndicator" class="<?php echo($isDoorOpen ? "doorIndicator_OPEN" : "doorIndicator_CLOSED"); ?>">
|
<div id="doorIndicator" class="<?php echo($doorEntry->open ? "doorIndicator_OPEN" : "doorIndicator_CLOSED"); ?>" onclick="location.href='/door/graph.html'">
|
||||||
<p class="doorStateText"><abbr title="Oppdatert <?php echo($doorTime) ?>">Døren er <b><?php echo($isDoorOpen ? "" : "ikke") ?> åpen</b>.</abbr></p>
|
<p class="doorStateText"><?php echo($doorStateText) ?></p>
|
||||||
<p class="doorStateTime doorStateMobileOnly">(Oppdatert <?php echo($doorTime) ?>)</p>
|
<p class="doorStateTime">(Oppdatert <?php echo($doorTime) ?>)</p>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,6 +26,31 @@ p {hyphens: auto;}
|
||||||
<p>Velkommen til Programvareverkstedets nettside. Programvareverkstedet (PVV) er en studentorganisasjon ved Norges Teknisk-Naturvitenskapelige Universitet (NTNU). PVVs formål er å skape et miljø for datainteresserte personer tilknyttet universitetet. Nåværende og tidligere studenter ved NTNU, samt ansatte ved NTNU og tilstøtende miljø, kan bli medlemmer.</p>
|
<p>Velkommen til Programvareverkstedets nettside. Programvareverkstedet (PVV) er en studentorganisasjon ved Norges Teknisk-Naturvitenskapelige Universitet (NTNU). PVVs formål er å skape et miljø for datainteresserte personer tilknyttet universitetet. Nåværende og tidligere studenter ved NTNU, samt ansatte ved NTNU og tilstøtende miljø, kan bli medlemmer.</p>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<style>
|
||||||
|
.iframe-container {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then style the iframe to fit in the container div with full height and width */
|
||||||
|
.responsive-iframe {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="iframe-container" style="max-width: 100em;">
|
||||||
|
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/l-iEkaQNQdk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
<h2>Hva betyr det å være et medlem av PVV?</h2>
|
<h2>Hva betyr det å være et medlem av PVV?</h2>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue