2024-02-19 03:44:40 +03:00

286 lines
8.5 KiB
JavaScript

var RE_WHITESPACE = /[\t\r\n\f]/g
var ajax = {
get: function(url, data) {
if (typeof data == 'object') {
var index = 0;
for (var key in data) {
var val = data[key];
url += index === 0 && url.indexOf('?') === -1 ? '?' : '&';
url += encodeURIComponent(key) + '=' + encodeURIComponent(val);
}
}
return this.raw(url);
},
post: function(url, body) {
var opts = {
method: 'POST'
};
if (body)
opts.body = body;
return this.raw(url, opts);
},
raw: function(url, options) {
if (!options)
options = {}
return fetch(url, Object.assign({
headers: {
'X-Requested-With': 'XMLHttpRequest',
}
}, options))
.then(resp => {
return resp.json()
})
}
};
function extend(a, b) {
return Object.assign(a, b);
}
function ge(id) {
return document.getElementById(id);
}
(function() {
var ua = navigator.userAgent.toLowerCase();
window.browserInfo = {
version: (ua.match(/.+(?:me|ox|on|rv|it|ra|ie)[\/: ]([\d.]+)/) || [0,'0'])[1],
//opera: /opera/i.test(ua),
msie: (/msie/i.test(ua) && !/opera/i.test(ua)) || /trident/i.test(ua),
mozilla: /firefox/i.test(ua),
android: /android/i.test(ua),
mac: /mac/i.test(ua),
samsungBrowser: /samsungbrowser/i.test(ua),
chrome: /chrome/i.test(ua),
safari: /safari/i.test(ua),
mobile: /iphone|ipod|ipad|opera mini|opera mobi|iemobile|android/i.test(ua),
operaMini: /opera mini/i.test(ua),
ios: /iphone|ipod|ipad|watchos/i.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1),
};
})();
function isTouchDevice() {
return 'ontouchstart' in window || navigator.msMaxTouchPoints;
}
function hasClass(el, name) {
if (!el)
throw new Error('hasClass: invalid element')
if (el.nodeType !== 1)
throw new Error('hasClass: expected nodeType is 1, got' + el.nodeType)
if (window.DOMTokenList && el.classList instanceof DOMTokenList) {
return el.classList.contains(name)
} else {
return (" " + el.className + " ").replace(RE_WHITESPACE, " ").indexOf(" " + name + " ") >= 0
}
}
function addClass(el, name) {
if (!hasClass(el, name)) {
el.className = (el.className ? el.className + ' ' : '') + name;
return true
}
return false
}
function removeClass(el, name) {
if (!el)
throw new Error('removeClass: invalid element')
if (Array.isArray(name)) {
for (var i = 0; i < name.length; i++)
removeClass(el, name[i]);
return;
}
el.className = ((el.className || '').replace((new RegExp('(\\s|^)' + name + '(\\s|$)')), ' ')).trim()
}
function indexInit() {
// language selector
var langSelect = document.getElementById('lang');
langSelect.addEventListener('change', function() {
var selectedLang = this.value;
document.cookie = "lang=" + selectedLang + ";path=/";
window.location.reload();
});
// camera blocks
var blocks = ['zones', 'list'];
for (var i = 0; i < blocks.length; i++) {
var button = ge('cam_'+blocks[i]+'_btn');
button.addEventListener('click', function(e) {
var selected = e.target.getAttribute('data-id');
for (var j = 0; j < blocks.length; j++) {
var button = ge('cam_'+blocks[j]+'_btn');
var content = ge('cam_'+blocks[j]);
if (blocks[j] === selected) {
addClass(button, 'active');
content.style.display = '';
} else {
removeClass(button, 'active');
content.style.display = 'none';
}
}
});
}
}
var Cameras = {
hlsOptions: null,
host: null,
proto: null,
hlsDebugVideoEvents: false,
getUrl: function(name) {
return this.proto + '://' + this.host + '/ipcam/' + name + '/live.m3u8';
},
setupHls: function(video, name, useHls) {
var src = this.getUrl(name);
// hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.
// When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element through the `src` property.
// This is using the built-in support of the plain video element, without using hls.js.
if (useHls) {
var config = this.hlsOptions;
config.xhrSetup = function (xhr,url) {
xhr.withCredentials = true;
};
var hls = new Hls(config);
hls.loadSource(src);
hls.attachMedia(video);
hls.on(Hls.Events.MEDIA_ATTACHED, function () {
video.muted = true;
video.play();
});
} else {
console.warn('hls.js is not supported, trying the native way...')
video.autoplay = true;
video.muted = true;
video.playsInline = true;
video.autoplay = true;
if (window.browserInfo.ios)
video.setAttribute('controls', 'controls');
video.src = src;
var events = ['canplay'];
if (this.hlsDebugVideoEvents)
events.push('canplay', 'canplaythrough', 'durationchange', 'ended', 'loadeddata', 'loadedmetadata', 'pause', 'play', 'playing', 'progress', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'waiting');
for (var i = 0; i < events.length; i++) {
var evt = events[i];
(function(evt, video, name) {
video.addEventListener(evt, function(e) {
if (this.debugVideoEvents)
console.log(name + ': ' + evt, e);
if (!window.browserInfo.ios && ['canplay', 'loadedmetadata'].includes(evt))
video.play();
})
})(evt, video, name);
}
}
},
init: function(opts) {
this.proto = opts.proto;
this.host = opts.host;
this.hlsOptions = opts.hlsConfig;
var useHls;
if (opts.hlsConfig !== undefined) {
useHls = Hls.isSupported();
if (!useHls && !this.hasFallbackSupport()) {
alert('Neither HLS nor vnd.apple.mpegurl is not supported by your browser.');
return;
}
}
for (var i = 0; i < opts.cams.length; i++) {
var camId = opts.cams[i]+'-low';
var video = document.createElement('video');
video.setAttribute('id', 'video-'+camId);
document.getElementById('videos').appendChild(video);
this.setupHls(video, camId, useHls);
}
},
hasFallbackSupport: function() {
var video = document.createElement('video');
return video.canPlayType('application/vnd.apple.mpegurl');
},
};
class ModemStatusUpdater {
constructor(id) {
this.id = id;
this.elem = ge('modem_data_'+id);
this.fetch()
}
fetch() {
ajax.get('/modems/info.ajx', {
id: this.id
}).then(({response}) => {
const {html} = response;
this.elem.innerHTML = html;
// TODO enqueue rerender
});
}
}
var ModemStatus = {
_modems: [],
init: function(modems) {
for (var i = 0; i < modems.length; i++) {
var modem = modems[i];
this._modems.push(new ModemStatusUpdater(modem));
}
}
};
var Inverter = {
poll: function () {
setInterval(this._tick, 1000);
},
_tick: function() {
ajax.get('/inverter.ajx')
.then(({response}) => {
if (response) {
var el = document.getElementById('inverter_status');
el.innerHTML = response.html;
}
});
}
};
(function () {
var htmlElement = document.querySelector("html")
if (htmlElement.getAttribute("data-bs-theme") === 'auto') {
function updateTheme() {
document.querySelector("html").setAttribute("data-bs-theme", window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light")
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateTheme);
updateTheme();
}
})()