strix

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

events.html (5358B)


      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 - Camera Events</title>
      7     <link href="/style.css" rel="stylesheet" type="text/css" />
      8 </head>
      9 <body>
     10     <div id="topview">
     11     <div id="viewer">
     12         <video controls autoplay=false playsinline=true></video>
     13     </div>
     14     <div id="days">
     15         <ul id="daylinks">
     16             <li><a id="imagelist" href="" target="_images">Images</a></li>
     17             <li><a id="debugvideo" onclick="">Debug</a></li>
     18             <li><a id="scrollback" onclick="">Jump Back</a></li>
     19         </ul>
     20     </div>
     21     </div>
     22     <div id="events"></div>
     23 
     24 
     25 <script type="text/javascript">
     26 var camera_events;
     27 
     28 function nice_short_time_string(time_str) {
     29     var arr = time_str.split(/[- :]/);
     30     var d = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
     31     // DoW Mo Day Year
     32     var fields = d.toDateString().split(" ");
     33     return fields.slice(0,3).join(" ");
     34 }
     35 
     36 function add_day(starttime) {
     37     let newLi = document.createElement("li");
     38     let newDay = document.createElement("a");
     39     newDay.innerHTML = nice_short_time_string(starttime);
     40     newDay.href = `#${starttime}`;
     41     newLi.appendChild(newDay);
     42 
     43     document.querySelector("#daylinks").appendChild(newLi);
     44 }
     45 
     46 function get_all_events(camera_name) {
     47     var last_start = 0;
     48 
     49     // The API returns the events with the oldest one first in the .events list
     50     fetch("/api/events/"+camera_name+"?limit=0")
     51         .then(resp => resp.json())
     52         .then(data => {
     53             // Save for onclick actions
     54             camera_events = data.events[camera_name];
     55             var events = document.querySelector("#events");
     56 
     57             // off-screen image used for onload to get width and height
     58             let oneImg = document.createElement("img");
     59             oneImg.onload = function() {
     60                 width = this.width;
     61                 height = this.height;
     62                 html = data.events[camera_name].reverse().map(event => {
     63                     let html = `<img class="thumbnail"
     64                             onclick="javascript:load_viewer('${event.video}', scrollY);"
     65                             title="${event.title}"
     66                             loading="lazy"
     67                             width=${width}
     68                             height=${height}
     69                             src="${event.thumbnail}" />`
     70                         // Show a day banner every time it passes midnight
     71                         if (last_start == 0) {
     72                             banner = `<div class="newday" id="${event.start}"><h1 align="center">${event.title}</h1>`;
     73                             html = banner + html;
     74                         } else {
     75                             var arr = last_start.split(/[- :]/);
     76                             let od = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]).getDay();
     77 
     78                             var arr = event.start.split(/[- :]/);
     79                             let nd = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]).getDay();
     80 
     81                             if (od != nd) {
     82                                 banner = `</div><div class="newday" id="${event.start}"><h1 align="center">${event.title}</h1>`;
     83                                 html = banner + html;
     84                                 add_day(event.start);
     85                             }
     86                         }
     87                         last_start = event.start;
     88                         return html;
     89                 }).join("");
     90                 events.innerHTML = html + "</div>";
     91             }
     92             // Load the 1st thumbnail, triggering onload for it
     93             oneImg.src = data.events[camera_name][0].thumbnail;
     94         });
     95 }
     96 
     97 function load_viewer(event, scrollY) {
     98     // Update the browser history and url with the new event
     99     let params = new URLSearchParams(document.location.search);
    100     params.set("event", event);
    101     window.history.pushState({}, document.title, "?"+params.toString());
    102 
    103     scroll(0,0);
    104 
    105     // Set the viewere to the event video
    106     var viewer = document.querySelector("#viewer video");
    107     viewer.src = event;
    108     viewer.autoplay = true;
    109 
    110     // Setup the Images link
    111     var il = document.querySelector("#imagelist");
    112     il.href = event.replace("video.m4v", "");
    113 
    114     // Setup the scrollback link
    115     var sb = document.querySelector("#scrollback");
    116     sb.onclick = function() {scroll(0, scrollY);};
    117 
    118     // Setup the debug link
    119     var dbg = document.querySelector("#debugvideo");
    120     dbg.onclick = function() {
    121         // Toggle between debug and normal view
    122         if (viewer.src.includes("debug/video.m4v")) {
    123             viewer.src = viewer.src.replace("debug/video.m4v", "video.m4v");
    124         } else {
    125             viewer.src = viewer.src.replace("video.m4v", "debug/video.m4v");
    126         }
    127     };
    128 
    129 }
    130 
    131 function setup_page() {
    132     let params = new URLSearchParams(document.location.search);
    133     let camera = params.get("camera");
    134     if (camera == null) {
    135         return;
    136     }
    137     let event = params.get("event");
    138 
    139     // Get the events for this camera from the API server and populate the page
    140     get_all_events(camera);
    141 
    142     // Load the viewer with the event, if one was selected
    143     if (event != null) {
    144         load_viewer(event, 0);
    145     }
    146 }
    147 
    148 setup_page();
    149 </script>
    150 </body>
    151 </html>