main
Michael Kowalczyk 1 year ago
parent 282feeb757
commit ea070245d5

@ -0,0 +1,13 @@
UI design principles - mostly adapted from https://maze.co/collections/ux-ui-design/ui-design-principles/
* Consistency (within the application and with similar applications)
* Provide easy navigation (logical hierarchy: navigating menus or tools for more options; multiple ways to carry out an action where it's natural to do so)
* Provide informative feedback (e.g. password strength)
* Design workflows to yield closure (e.g. "purchase complete", "file saved")
* Prevent user errors (e.g. "are you sure you want to exit without saving?")
* Allow users ways to reverse their actions easily (e.g. undo, redo, cancel, and exit)
* Avoid surprises and changes in behavior
* Minimize the user's memory load (avoid having to remember things in order to perform a task, e.g. "I forgot that I already bought that book.")
* Aim for clarity (quickly and easily understand what something does)
* Use visual hierarchy (size, color, font, white space, and negative space) to illustrate what is important and what groups together
* Design for flexibility: Accommodate different user skill levels (e.g. mouse vs keyboard shortcuts, advanced features, filters) and disabilities (color contrast, screen reader, easy tab key navigation, for web: different devices)
* Lead the user to formulate a good mental model of what happens internally

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

@ -0,0 +1,264 @@
function scaleMap(page, r) {
var map = page.querySelector("map");
var container = page.querySelector(".ImageContainer > .Links");
if (!container) {
container = document.createElement("div");
container.setAttribute("class", "Links");
page.querySelector(".ImageContainer").appendChild(container);
} else {
container.innerHTML = "";
}
map.querySelectorAll("area").forEach(function (area) {
var original = area._originalCoords || area.getAttribute("coords");
area._originalCoords = original;
var coords = original.split(/\,/).map(function (v) {
return Math.round(parseFloat(v) / r);
});
area.setAttribute("coords", coords.join(","));
var a = document.createElement("a");
a.style.left = convertRatio(coords[0]) + "px";
a.style.top = convertRatio(coords[1]) + "px";
a.style.width = convertRatio(coords[2] - coords[0]) + "px";
a.style.height = convertRatio(coords[3] - coords[1]) + "px";
a.setAttribute("href", area.getAttribute("href"));
container.appendChild(a);
});
}
function convertRatio(value) {
return parseFloat(value); // * window.devicePixelRatio;
}
function fitImages() {
var pages = document.querySelectorAll("body > div.Page");
var W = 0;
var H = 0;
var activePage = null;
pages.forEach(function (page) {
if (page.offsetWidth == 0 || page.offsetHeight == 0) return;
W = page.offsetWidth - (window.useExpandedMode ? 200 : 40);
H = page.offsetHeight - 40;
activePage = page;
});
if (activePage && window.lastActivePage != activePage) {
window.useExpandedMode = false;
invalidateExpandMode("dontFit");
window.lastSize = null;
document.body.querySelectorAll(".TOC > div").forEach(function (item) {
var matched = item.classList.contains("Page_" + activePage.id);
if (matched) {
document.title = item._name + " - " + window.originalTitle;
item.classList.add("Focused");
item.focus();
} else {
item.classList.remove("Focused");
}
});
window.lastActivePage = activePage;
}
if (W && H) {
if (window.lastSize && window.lastSize.W == W && window.lastSize.H == H) return;
var imgs = document.querySelectorAll("body > div.Page img");
imgs.forEach(function (img) {
var r = window.useExpandedMode ? Math.min(img.naturalWidth / W, img.naturalHeight / H) : Math.max(img.naturalWidth / W, img.naturalHeight / H);
if (r < 1 && !window.useExpandedMode) r = 1;
var w = Math.round(img.naturalWidth / r);
var h = Math.round(img.naturalHeight / r);
img.style.width = w + "px";
img.style.height = h + "px";
img.setAttribute("width", w);
img.setAttribute("height", h);
var page = img;
while (!page.classList.contains("Page")) page = page.parentNode;
scaleMap(page, r * (img._originalWidth / img.naturalWidth));
});
window.lastSize = {W: W, H: H};
}
}
function checkActivePage() {
var pages = document.querySelectorAll("body > div.Page");
var found = false;
var firstPage = null;
pages.forEach(function (page) {
if (!firstPage) firstPage = page;
if (page.offsetWidth != 0 && page.offsetHeight != 0) found = true;
});
if (!found && firstPage) {
location.hash = "#" + firstPage.id;
fitImages();
}
}
function workingThreadFunction() {
try {
try {
fitImages();
} catch (e) {
console.error(e);
}
try {
checkActivePage();
} catch (e) {
console.error(e);
}
} catch (e) {
console.error(e);
} finally {
window.setTimeout(workingThreadFunction, 300);
}
}
var idleTimeout = null;
function handleMouseMove() {
if (!document.body.classList.contains("Active")) {
document.body.classList.add("Active");
}
if (idleTimeout) window.clearTimeout(idleTimeout);
idleTimeout = window.setTimeout(function () {
document.body.classList.remove("Active");
idleTimeout = null;
}, 400);
}
var THUMB_WIDTH = 250;
var THUMB_HEIGHT = 160;
var THUMB_DISPLAY_SIZE = 160;
function buildThumbnail(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var r = Math.max(image.width / THUMB_WIDTH, image.height / THUMB_HEIGHT);
var w = image.width / r, h = image.height / r;
canvas.width = w;
canvas.height = h;
ctx.drawImage(image, 0, 0, w, h);
callback(canvas.toDataURL('image/png'), w, h);
};
image.src = url;
}
function generateTOC() {
var toc = document.createElement("div");
toc.setAttribute("class", "TOC");
var pages = document.querySelectorAll("body > div.Page");
pages.forEach(function (page) {
var title = page.querySelector("h2");
var img = page.querySelector(".ImageContainer img");
var item = document.createElement("div");
var imageWrapper = document.createElement("a");
var itemImage = document.createElement("img");
item.classList.add("Page_" + page.id);
item.setAttribute("tabindex", 0);
item._name = title.textContent;
imageWrapper.setAttribute("href", "#" + page.id);
item.appendChild(imageWrapper);
var name = document.createElement("strong");
name.innerHTML = title.innerHTML;
toc.appendChild(item);
buildThumbnail(img.src, function (dataUrl, w, h) {
var r = Math.max(w / THUMB_DISPLAY_SIZE, h / THUMB_DISPLAY_SIZE);
var w = w / r, h = h / r;
imageWrapper.appendChild(itemImage);
itemImage.style.width = w + "px";
itemImage.style.height = h + "px";
itemImage.src = dataUrl;
imageWrapper.appendChild(name);
});
});
document.body.appendChild(toc);
}
function invalidateExpandMode(dontFit) {
if (window.useExpandedMode) {
document.body.classList.add("ExpandMode");
} else {
document.body.classList.remove("ExpandMode");
}
if (!dontFit) fitImages();
}
function boot() {
window.originalTitle = document.title;
document.addEventListener("mousemove", handleMouseMove);
var style = document.createElement("link");
style.setAttribute("rel", "stylesheet");
style.setAttribute("href", "Resources/style.css");
document.querySelector("head").appendChild(style);
var imgs = document.querySelectorAll("body > div.Page img");
imgs.forEach(function (img) {
img._originalWidth = parseInt(img.getAttribute("width"), 10);
img._originalHeight = parseInt(img.getAttribute("height"), 10);
});
generateTOC();
workingThreadFunction();
window.zoomToggleButton = document.createElement("button");
window.zoomToggleButton.classList.add("ToggleZoomButton");
window.zoomToggleButton.setAttribute("title", "Toggle expand/fit mode");
document.body.appendChild(window.zoomToggleButton);
window.zoomToggleButton.addEventListener("click", function () {
window.useExpandedMode = window.useExpandedMode ? false : true;
window.lastSize = null;
invalidateExpandMode();
}, false);
}
window.onload = boot;

@ -0,0 +1,169 @@
/*
place extra stylesheet here
*/
body, html {
margin: 0px;
padding: 0px;
overflow: hidden;
font-family: "Product Sans", "Liberation Sans", Arial, sans-serif;
}
#documentMetadata,
#documentTitle {
display: none;
}
.Page {
position: absolute;
left: 230px;
top: 0px;
right: 0px;
bottom: 0px;
background: #00000077;
text-align: center;
}
body:not(.ExpandMode) .Page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
body.ExpandMode .Page {
overflow: auto;
padding: 20px;
text-align: center;
}
.Page:not(:target) {
display: none !important;
}
.Page > h2 {
display: none;
}
.Page .ImageContainer {
box-shadow: 0px 0px 1em #00000077;
}
body.ExpandMode .Page .ImageContainer {
display: inline-block;
margin-bottom: 20px;
}
.Page .ImageContainer {
position: relative;
}
.Page .ImageContainer > .Links > a {
position: absolute;
background-color: transparent;
transition: background-color 0.2s ease;
}
body.Active .Page .ImageContainer > .Links > a {
background-color: #E79A0F11;
}
.Page .ImageContainer > .Links > a:hover {
background-color: #FFFFFF55 !important;
}
.TOC {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
width: 230px;
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: visible;
z-index: 2;
background: #444;
}
.TOC > div {
display: flex;
flex-direction: column;
}
.TOC > div.Focused > a {
background: #5294E2;
}
.TOC > div:not(.Focused):hover > a {
background: #5294E266;
}
.TOC > div:not(.Focused):not(:hover) {
opacity: 0.7;
}
.TOC > div + div {
margin-top: 1em;
}
.TOC > div > a {
flex: 1 1 auto;
display: flex;
flex-direction: column;
align-items: center;
padding: 1em;
background: transparent;
transition: background 0.2s ease;
text-decoration: none;
}
.TOC > div > a > img {
display: block;
border: solid 2px #FFF;
box-shadow: 0px 0px 5px #000;
}
.TOC > div > a > strong {
display: block;
text-align: center;
color: #FFF;
font-weight: normal;
margin-top: 0.3em;
}
.ToggleZoomButton {
position: fixed;
top: 0.5em;
right: 0.5em;
width: 1.5em;
height: 1.5em;
padding: 0.3em;
box-sizing: content-box;
background: url(expand.png) 50% 50% no-repeat #CCCCCC;
background-origin: content-box;
background-size: contain;
border: solid 1px #777;
}
.ToggleZoomButton:active {
margin-top: 1px;
margin-left: 1px;
}
.ToggleZoomButton:not(:hover) {
opacity: 0.3;
}
body.ExpandMode .ToggleZoomButton {
background-image: url(fit.png)
}

@ -0,0 +1,2 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:p="http://www.evolus.vn/Namespace/Pencil" xmlns:html="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Campus Visit Prototype</title><link rel="stylesheet" href="Resources/style.css" /><script type="application/javascript" src="Resources/script.js"></script></head><body><h1 id="documentTitle">Campus Visit Prototype</h1><p id="documentMetadata">Exported at: Wed Sep 18 2024 09:38:34 GMT-0400 (Eastern Daylight Time)</p><div class="Page" id="users_page"><h2>Users</h2><div class="ImageContainer"><img src="pages\users.png" width="887" height="470" usemap="#map_users" /></div><map name="map_users"><area shape="rect" coords="103.00007629394531,41.452125549316406,193.000068664551,75.7999305725098" href="#visits_page" title="Go to page 'Visits'" /><area shape="rect" coords="648,184.0000457763672,755,209.000045776367" href="#availability_page" title="Go to page 'Availability'" /><area shape="rect" coords="648,149.00003051757812,755,174.00004196167" href="#availability_page" title="Go to page 'Availability'" /><area shape="rect" coords="648,114.00005340576172,755,139.750064849854" href="#availability_page" title="Go to page 'Availability'" /></map></div><div class="Page" id="availability_page"><h2>Availability</h2><div class="ImageContainer"><img src="pages\availability.png" width="355" height="216" usemap="#map_availability" /></div><map name="map_availability"><area shape="rect" coords="0.9999974966049194,0.0000032186512726184446,354.999997496605,215.000003218651" href="#users_page" title="Go to page 'Users'" /></map></div><div class="Page" id="visits_page"><h2>Visits</h2><div class="ImageContainer"><img src="pages\visits.png" width="887" height="496" usemap="#map_visits" /></div><map name="map_visits"><area shape="rect" coords="747,408.00006103515625,837,433.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,379.00006103515625,837,404.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,321.00006103515625,837,346.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,350.00006103515625,837,375.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,291.00006103515625,837,316.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,236.0000457763672,837,261.000066757202" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,263.00006103515625,837,288.000061035156" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,207.0000457763672,837,232.000045776367" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="747,179.0000457763672,837,204.000045776367" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="746,151.00003051757812,836,176.00004196167" href="#visitdetails_page" title="Go to page 'VisitDetails'" /><area shape="rect" coords="17.000059127807617,40.452110290527344,107.000059127808,74.7999153137207" href="#users_page" title="Go to page 'Users'" /></map></div><div class="Page" id="visitdetails_page"><h2>VisitDetails</h2><div class="ImageContainer"><img src="pages\visitdetails.png" width="691" height="492" usemap="#map_visitdetails" /></div><map name="map_visitdetails"><area shape="rect" coords="205.0000457763672,456,359.000091552734,481" href="#visits_page" title="Go to page 'Visits'" /></map></div></body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Loading…
Cancel
Save