<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Cache-Control" content="no-cache,no-store,must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<style style="text/css">
body {
margin: 0;
max-height: 100vh;
height: 100vh;
height: 100%;
background: #343a3f;
color: #FFF;
font-family: Helvetica;
text-align: center;
display: grid;
grid-template-rows: 1fr 5fr;
grid-template-columns: 1fr 5fr;
grid-template-areas:
"header header"
"nav main";
grid-gap: .25em;
}
header {
grid-area: header;
}
nav {
grid-area: nav;
overflow: auto;
}
main {
grid-area: main;
overflow: hidden;
}
header, nav, main {
border: 1px solid rgba(255,255,255,0.8);
border-radius: 3px;
}
.controls button {
background-color: #4CAF50;
color: white;
border: 0;
font-family: Helvetica;
text-decoration: none;
display: inline-block;
padding: 8px 16px;
margin: 3px;
}
.controls button:hover {
background-color: #ddd;
color: black;
}
.groups ul {
padding: 0 0 0 0;
list-style: none;
text-align: left;
}
.groups li {
padding: 2px 0 2px 32px;
}
</style>
</head>
<script src="jscript/shine/shine.js"></script>
<script src="jscript/svg-pan-zoom/svg-pan-zoom.min.js" type="text/javascript"></script>
<script src="jscript/stats/stats.min.js"></script>
<script type="text/javascript">
var images = {{ svg_list | safe }};
var image_id = 0;
var stats, shine;
var svg = null;
var svgPreserveSize = [];
var panZoom = null;
function init() {
shine = new Shine();
stats = new Stats();
document.body.appendChild(stats.dom);
}
function releaseSVG() {
let groupContent = document.getElementById('groups');
while (groupContent.firstChild) {
groupContent.removeChild(groupContent.firstChild);
}
let svgContent = document.getElementById('svgContainer');
while (svgContent.firstChild) {
svgContent.removeChild(svgContent.firstChild)
}
if (panZoom) {
panZoom.destroy();
panZoom = null;
}
svg = null;
svgPreserveSize.length = 0;
}
function createGroupItem(groupContent, node, name) {
let checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = true;
checkbox.onchange = function (event) {
let visible = event.target.checked;
node.setAttribute('opacity', visible ? '1' : '0');
};
let label = document.createElement('label')
label.appendChild(document.createTextNode(name));
let li = document.createElement('li')
li.appendChild(checkbox);
li.appendChild(label);
groupContent.appendChild(li);
return li;
}
function createSVG() {
let titleContent = document.getElementById('title');
let svgContent = document.getElementById('svgContainer');
let groupContent = document.getElementById('groups');
if (image_id < 0 || image_id >= images.length) {
svgContent.innerHTML = ""
titleContent.innerHTML = "Image - None" + "/" + (images.length).toString()
return;
}
svgContent.innerHTML = images[image_id];
titleContent.innerHTML = "Image - " + (image_id + 1).toString() + "/" + (images.length).toString()
let childNodes = svgContent.childNodes;
for (let i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeName == 'svg') {
svg = childNodes[i];
break;
}
}
svg.setAttribute('style', 'display: inline; min-width: 100%; min-height: 100%; max-width: 100%; max-height: 100%')
let openNodes = [[svg, groupContent]];
let auto_id = 0;
while (openNodes.length > 0) {
let current = openNodes.pop();
let children = current[0].children;
let docParent = current[1];
let listParent = undefined;
for (let i = 0; i < children.length; i++) {
let node = children[i];
if (node.tagName == 'g') {
let name = node.getAttribute('group-name');
auto_id += 1;
if (!name) { 'group_' + auto_id; }
if (node.getAttribute('preserve-size')) {
svgPreserveSize.push(node);
}
let childNode;
if (name != '*') {
if (!listParent) {
listParent = docParent.appendChild(document.createElement('ul'));
}
childNode = createGroupItem(listParent, node, name);
}
else {
childNode = docParent;
}
openNodes.push([node, childNode]);
}
}
}
panZoom = svgPanZoom('svg', {
zoomEnabled: true,
controlIconsEnabled: true,
fit: true,
center: true,
zoomScaleSensitivity: 0.5,
onZoom: function (v) {
let scl = 1 / v;
svgPreserveSize.forEach(node => {
let trsf = node.getAttribute('transform').replace(/scale\(([^)]+)\)/i, 'scale(' + scl + ')');
node.setAttribute('transform', trsf);
})
}
});
}
function selectSVG(id, preserveZoom, preserveVisibility) {
image_id = id
if (image_id < 0) image_id = 0;
if (image_id >= images.length) image_id = images.length - 1;
if (!panZoom) {
createSVG();
return
}
let zoom = panZoom.getZoom();
let pan = panZoom.getPan();
releaseSVG();
createSVG();
if (panZoom && preserveZoom) {
panZoom.zoom(zoom);
panZoom.pan(pan);
}
}
function step(delta) {
console.log(delta)
selectSVG(image_id + delta, true, true)
}
function animate() {
requestAnimationFrame(animate);
stats.update();
}
function onWindowResize() {
if (panZoom) {
panZoom.resize();
panZoom.fit();
panZoom.center();
};
}
window.onload = function () {
init();
selectSVG(0, false, false);
animate();
}
window.onresize = function () {
onWindowResize();
}
</script>
<body>
<header>
<h1 id="title">Image</h1>
<div class="controls">
<button onclick="step(Number.MIN_SAFE_INTEGER)">First</button>
<button onclick="step(-10)">« « Previous</button>
<button onclick="step(-1)">« Previous</button>
<button onclick="step(1)">Next »</button>
<button onclick="step(10)">Next » »</button>
<button onclick="step(Number.MAX_SAFE_INTEGER)">Last</button>
</div>
<div class="controls">
<button onclick="location.reload(true)">Refresh</button>
<button onclick="shine.notifyUser();location.reload(true)">Continue</button>
</div>
</header>
<nav>
<div id="groups" class="groups" />
</nav>
<main>
<div id="svgContainer" style="height: 100%;" />
</main>
</body>
</html>