index.html (4604B)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset=UTF-8> 5 <meta name="viewport" content="width=device-width"> 6 <title>Strix - Motion Camera UI</title> 7 <link href="/style.css" rel="stylesheet" type="text/css" /> 8 </head> 9 <body> 10 <div id="live-feeds"> 11 </div> 12 <script type="text/javascript"> 13 var cameras = []; 14 15 function set_feed_href() { 16 var feeds = Array.from(document.querySelectorAll(".feed-href")); 17 feeds.forEach(feed => { 18 feed.href = "//" + location.hostname + ":" + feed.attributes["data-port"].value; 19 }); 20 } 21 22 function set_feed_src() { 23 var feeds = Array.from(document.querySelectorAll(".feed-src")); 24 feeds.forEach(feed => { 25 feed.src = "//" + location.hostname + ":" + feed.attributes["data-port"].value + "/video.mjpeg?rand=" + Math.random(); 26 }); 27 } 28 29 function get_events(camera_name, offset, limit) { 30 // The API returns the events with the oldest one first in the .events list 31 fetch("/api/events/"+camera_name+"?offset="+offset+"&limit="+limit) 32 .then(resp => resp.json()) 33 .then(data => { 34 var idx = 0; 35 var videos = Array.from(document.querySelectorAll("#"+camera_name+" td.thumbnails div > a")) 36 videos.forEach(video => { 37 event = data.events[camera_name][idx]; 38 video.href="events.html?camera="+camera_name+"&event="+event.video; 39 video.title=event.title; 40 img = video.firstChild; 41 img.src = event.thumbnail; 42 idx++; 43 }); 44 }); 45 } 46 47 function prev_events(e) { 48 // e.target.offsetParent.ParentNode.id has the CameraX class 49 // Not too sure how reliable that is... 50 let camera_name = e.target.offsetParent.parentNode.id; 51 event_offsets.set(camera_name, event_offsets.get(camera_name) + 5); 52 get_events(camera_name, event_offsets.get(camera_name), 5); 53 54 } 55 56 function next_events(e) { 57 let camera_name = e.target.offsetParent.parentNode.id; 58 if(event_offsets.get(camera_name) >=5) { 59 event_offsets.set(camera_name, event_offsets.get(camera_name) - 5); 60 } else { 61 event_offsets.set(camera_name, 0); 62 } 63 get_events(camera_name, event_offsets.get(camera_name), 5); 64 } 65 66 // Update all thumbnails that haven't been changed by the user 67 function update_events() { 68 cameras.map(camera => { 69 var camera_name = camera[0]; 70 if (event_offsets.get(camera_name) == 0) { 71 get_events(camera_name, 0, 5); 72 } 73 }); 74 } 75 76 function setup_page() { 77 event_offsets = new Map(); 78 79 // Setup the camera HTML 80 var live_feeds = document.querySelector("#live-feeds"); 81 var html = cameras.map(camera => { 82 var camera_name = camera[0]; 83 var port = camera[1]; 84 return `<div class="feed" id="${camera_name}"> 85 <table> 86 <tr><a href="" class="feed-href" data-port="${port}"><img src="#" class="feed-src" data-port="${port}"></a></tr> 87 <tr class="controls"> 88 <td class="prev"><</td> 89 <td class="thumbnails"><div> 90 <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> 91 </div></td> 92 <td class="next">></td></tr> 93 </table> 94 </div>`; 95 }).join(""); 96 live_feeds.innerHTML = html; 97 98 set_feed_href(); 99 set_feed_src(); 100 101 var prev_buttons = Array.from(document.querySelectorAll(".prev")); 102 prev_buttons.forEach(button => button.addEventListener("click", prev_events)); 103 var next_buttons = Array.from(document.querySelectorAll(".next")); 104 next_buttons.forEach(button => button.addEventListener("click", next_events)); 105 106 // Grab the initial events for each camera 107 cameras.map(camera => { 108 var camera_name = camera[0]; 109 var port = camera[1]; 110 event_offsets.set(camera_name, 0); 111 get_events(camera_name, 0, 5); 112 }); 113 114 // Update un-modified thumbnails every 30 seconds 115 setInterval(update_events, 30 * 1000); 116 } 117 118 // First thing to do is get the list of cameras, then setup the page. 119 fetch("/api/cameras/list") 120 .then(resp => resp.json()) 121 .then(data => { 122 // This is a global variable, used by several functions 123 cameras = data.cameras; 124 setup_page(); 125 }); 126 </script> 127 </body> 128 </html>