Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/views/application/_menu.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@
<!-- Right part -->
<div class="hidden md:block">
<div class="flex items-center">
<iframe sandbox="allow-scripts allow-popups allow-same-origin"
id="zappbutton"
src="https://zapp.zeus.gent/zapp-iframe/button.html"
style="height: 3.7em; aspect-ratio: 1 / 1; border: none; overflow: hidden; scrollbar-width: 0;"
>
</iframe>

<!-- Notifications -->
<%= link_to user_notifications_path(current_user),
class: 'flex items-center bg-gray-800 p-2 rounded-md text-gray-400 hover:bg-gray-700 hover:text-white' do %>
Expand Down
11 changes: 11 additions & 0 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>

<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
<script src='/scripts/zapp-iframe.js' async></script>
</head>

<body class="h-full">
Expand Down Expand Up @@ -43,6 +44,16 @@

</div>

<!-- Zapp Dropdown iframe needs to be directly relative to body -->
<!-- local testing: -->
<!-- production: https://zapp.zeus.gent/zapp-iframe/dropdown.html -->

<iframe sandbox="allow-scripts allow-popups allow-same-origin"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to add more allows here to fix ZeusWPI/ZAPP#1?

id="zappdropdown"
src="https://zapp.zeus.gent/zapp-iframe/dropdown.html"
style="border-style: none; z-index: 200; position: absolute; left: 0; top: 0; height: 0vh; width: 0vw; overflow: hidden; visibility: hidden;"
></iframe>

<footer class="p-4 bg-white shadow md:flex md:items-center md:justify-between md:p-6 dark:bg-gray-800">
<span class="text-sm text-gray-500 sm:text-center dark:text-gray-400">© <%= Date.current.year %> <a href="https://zeus.gent" class="hover:underline">Zeus WPI</a>. All Rights Reserved.
</span>
Expand Down
93 changes: 93 additions & 0 deletions public/scripts/zapp-iframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
let setsize = false;
let dropwidth = 0;
let dropheight = 0;
let opened = false;

const outsideclickhandler = (ev) => {
const path = ev.composedPath();
const clickedInside =
path.some((n) => n && n.id === 'zappbutton') ||
path.some((n) => n && n.id === 'zappdropdown');
if (!clickedInside) {
opened = false;
const dropdown = document.getElementById("zappdropdown");
dropdown.style.visibility = opened ? "visible" : "hidden";
dropdown.contentWindow.postMessage({type: "outsideclick"}, "*")
document.getElementById("zappbutton").contentWindow.postMessage({type: "outsideclick"}, "*")
dropdown.contentWindow.postMessage({type: "outsideclick"}, "*")
}
};
window.addEventListener("click", outsideclickhandler);
const GAP = 4;

function position(){
var dropdownroot = document.getElementById("zappdropdown")
const vrect = document.getElementById("zappbutton").getBoundingClientRect();

const vw = window.innerWidth;
const vh = window.innerHeight;

let left = vrect.x;
let topBelow = vrect.y + vrect.height + GAP;
let top = topBelow;

// Horizontal clamp
if(left + dropwidth > vw - GAP) left = Math.max(GAP, vw - dropwidth - GAP);
if(left < GAP) left = GAP;

// Prefer below, fallback above if overflow
if(top + dropheight > vh - GAP){
const topAbove = vrect.y - dropheight - GAP;
if(topAbove >= GAP){
top = topAbove;
}else{
// Clamp inside viewport
top = Math.max(GAP, Math.min(top, vh - dropheight - GAP));
}
}

// dropdownroot.style.left = left + "px";
dropdownroot.style.transform = `translatex(${left}px)`
dropdownroot.style.top = top + "px";
}

function openAnimation(){
const root = document.getElementById("zappdropdown")
// Avoid duplicating listeners
if(!root._repositionBound){
const handler = () => position();
window.addEventListener("resize", handler);
window.addEventListener("scroll", handler, true);
root._repositionBound = true;
}
position();
}

window.onmessage = function(e){
const button = document.getElementById("zappbutton");
const dropdown = document.getElementById("zappdropdown");
try{
let msg = JSON.parse(e.data);
if(msg.type === "buttonclick"){
opened = !opened;
dropdown.style.visibility = opened ? "visible" : "hidden";
dropdown.contentWindow.postMessage({type: 'state', state: opened}, "*")
if(opened) openAnimation();
}else if(msg.type === "dropdown-box" && !setsize){
setsize = true;
dropwidth = msg.box.width;
dropheight = msg.box.height;
dropdown.style.width = `${dropwidth}px`;
dropdown.style.height = `${dropheight + 7}px`;
}else if(msg.type === "state"){
opened = msg.state;
dropdown.style.visibility = opened ? "visible" : "hidden";
button.contentWindow.postMessage(msg, "*")
}
else{
console.error("no supported msg type: " + msg.type)
}
}catch(err){
console.error(err);
}
}