strix

A simple web UI for motion
git clone https://www.brianlane.com/git/strix
Log | Files | Refs | LICENSE

commit a986deb81a52689e5a69bab736052402579eebec
parent 60515f688f4bfa4a8ad5fdc8625f02a77eea1573
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Sun, 19 Jul 2020 14:38:21 -0700

Fix the page glitch when scrolling through videos

Changing innerHTML makes it collapse the elements and re-fill them.
Instead it is better to pre-populate the videos with a/img elements and
then in the event handler fill them in with the links on each click.

This prevents the layout from collapsing, and makes the page stop
jumping up when you are at the bottom on scroll through the thumbnails
from camera #3

Diffstat:
Msrc/bin/strix | 2+-
Msrc/strix/ui/index.html | 67+++++++++++++++++++++++++++++++++++++------------------------------
Msrc/strix/ui/style.css | 2++
3 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/bin/strix b/src/bin/strix @@ -2,7 +2,7 @@ # # strix # -# Copyright (C) 2017 Brian C. Lane +# Copyright (C) 2017-2020 Brian C. Lane # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/strix/ui/index.html b/src/strix/ui/index.html @@ -1,21 +1,24 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<!DOCTYPE html> <html lang="en"> <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta charset=UTF-8> <meta name="viewport" content="width=device-width"> <title>Strix - Motion Camera UI</title> <link href="/style.css" rel="stylesheet" type="text/css" /> </head> +<body> +<div id="live-feeds"> +</div> <script type="text/javascript"> function set_feed_href() { - const feeds = Array.from(document.querySelectorAll(".feed-href")); + var feeds = Array.from(document.querySelectorAll(".feed-href")); feeds.forEach(feed => { feed.href = "//" + location.hostname + ":" + feed.attributes["data-port"].value; }); } function set_feed_src() { - const feeds = Array.from(document.querySelectorAll(".feed-src")); + var feeds = Array.from(document.querySelectorAll(".feed-src")); feeds.forEach(feed => { feed.src = "//" + location.hostname + ":" + feed.attributes["data-port"].value; }); @@ -33,15 +36,16 @@ function get_events(camera_name, offset, limit) { fetch("/api/events/"+camera_name+"?offset="+offset+"&limit="+limit) .then(resp => resp.json()) .then(data => { - const camera_div = document.querySelector("div#"+camera_name+" td.thumbnails"); - console.log(data); - const html = data.events[camera_name].map(event => { - var start = nice_time_string(event.start); - return `<a href="/${event.video}" class="video" title="${start}" target="video"><img class="thumbnail" src="/${event.thumbnail}" /></a>`; - }).join(""); - new_div = document.createElement("div"); - new_div.innerHTML = html; - camera_div.replaceChild(new_div, camera_div.childNodes[0]); + var idx = 0; + var videos = Array.from(document.querySelectorAll("#"+camera_name+" td.thumbnails div > a")) + videos.forEach(video => { + event = data.events[camera_name][idx]; + video.href=event.video; + video.title=nice_time_string(event.start); + img = video.firstChild; + img.src = event.thumbnail; + idx++; + }); }); } @@ -49,22 +53,18 @@ function prev_events(e) { // e.target.offsetParent.ParentNode.id has the CameraX class // Not too sure how reliable that is... let camera_name = e.target.offsetParent.parentNode.id; - console.log("Clicked Prev for "+camera_name); event_offsets.set(camera_name, event_offsets.get(camera_name) + 5); - console.log(camera_name+" offset is "+event_offsets.get(camera_name)); get_events(camera_name, event_offsets.get(camera_name), 5); } function next_events(e) { let camera_name = e.target.offsetParent.parentNode.id; - console.log("Clicked Next for "+camera_name); if(event_offsets.get(camera_name) >=5) { event_offsets.set(camera_name, event_offsets.get(camera_name) - 5); } else { event_offsets.set(camera_name, 0); } - console.log(camera_name+" offset is "+event_offsets.get(camera_name)); get_events(camera_name, event_offsets.get(camera_name), 5); } @@ -75,39 +75,46 @@ function setup_page() { event_offsets = new Map(); // Setup the camera HTML - const live_feeds = document.querySelector("div#live-feeds"); - const html = cameras.map(camera => { - const camera_name = camera[0]; - const port = camera[1]; + var live_feeds = document.querySelector("#live-feeds"); + var html = cameras.map(camera => { + var camera_name = camera[0]; + var port = camera[1]; return `<div class="feed" id="${camera_name}"> <table> <tr><a href="" class="feed-href" data-port="${port}"><img src="" class="feed-src" data-port="${port}"></a></tr> - <tr class="controls"><td class="prev">&lt</td><td class="thumbnails"><div /></td><td class="next">&gt</td></tr> + <tr class="controls"> + <td class="prev">&lt</td> + <td class="thumbnails"><div> + <a class="video" target="video" href="/"><img class="thumbnail" src="/" /></a> + <a class="video" target="video" href="/"><img class="thumbnail" src="/" /></a> + <a class="video" target="video" href="/"><img class="thumbnail" src="/" /></a> + <a class="video" target="video" href="/"><img class="thumbnail" src="/" /></a> + <a class="video" target="video" href="/"><img class="thumbnail" src="/" /></a> + </div></td> + <td class="next">&gt</td></tr> </table> </div>`; }).join("\n"); - console.log(html) live_feeds.innerHTML = html; set_feed_href(); set_feed_src(); - const prev_buttons = Array.from(document.querySelectorAll(".prev")); + var prev_buttons = Array.from(document.querySelectorAll(".prev")); prev_buttons.forEach(button => button.addEventListener("click", prev_events)); - const next_buttons = Array.from(document.querySelectorAll(".next")); + var next_buttons = Array.from(document.querySelectorAll(".next")); next_buttons.forEach(button => button.addEventListener("click", next_events)); // Grab the initial events for each camera cameras.map(camera => { - const camera_name = camera[0]; - const port = camera[1]; + var camera_name = camera[0]; + var port = camera[1]; event_offsets.set(camera_name, 0); get_events(camera_name, 0, 5); }); } + +setup_page(); </script> -<body onload="setup_page();"> -<div id="live-feeds"> -</div> </body> </html> diff --git a/src/strix/ui/style.css b/src/strix/ui/style.css @@ -23,6 +23,8 @@ td.prev:hover,td.next:hover { .feed table { border-spacing: 0px; + display: block; + width: 100%; } img.thumbnail {