diff options
-rw-r--r-- | localwebsite/config.php | 4 | ||||
-rw-r--r-- | localwebsite/htdocs/assets/app.css | 39 | ||||
-rw-r--r-- | localwebsite/htdocs/assets/app.js | 153 | ||||
-rw-r--r-- | localwebsite/templates-web/cams.twig | 85 |
4 files changed, 158 insertions, 123 deletions
diff --git a/localwebsite/config.php b/localwebsite/config.php index f5f8c80..68c1ed5 100644 --- a/localwebsite/config.php +++ b/localwebsite/config.php @@ -49,8 +49,8 @@ return [ ], 'static' => [ - 'app.css' => 9, - 'app.js' => 2, + 'app.css' => 10, + 'app.js' => 4, 'polyfills.js' => 1, 'modem.js' => 1, 'inverter.js' => 2, diff --git a/localwebsite/htdocs/assets/app.css b/localwebsite/htdocs/assets/app.css index 59c0f35..d93c4f7 100644 --- a/localwebsite/htdocs/assets/app.css +++ b/localwebsite/htdocs/assets/app.css @@ -152,25 +152,22 @@ 40% { opacity: 1; } } -/* cams page */ -@media only screen and (min-width: 640px) { - .camfeeds { - display: flex; - flex-wrap: wrap; - flex-direction: row; - } - .camfeeds > video { - display: flex; - flex-basis: calc(50% - 20px); - justify-content: center; - flex-direction: column; - width: calc(50% - 10px); - margin: 5px; - } -} -@media only screen and (max-width: 639px) { - .camfeeds > video { - max-width: 100%; - } -}
\ No newline at end of file +.camfeeds:not(.is_mobile) { + display: flex; + flex-wrap: wrap; + flex-direction: row; +} + +.camfeeds:not(.is_mobile) > video { + display: flex; + flex-basis: calc(50% - 20px); + justify-content: center; + flex-direction: column; + width: calc(50% - 10px); + margin: 5px; +} + +.camfeeds.is_mobile > video { + max-width: 100%; +} diff --git a/localwebsite/htdocs/assets/app.js b/localwebsite/htdocs/assets/app.js index c08490f..ff2295d 100644 --- a/localwebsite/htdocs/assets/app.js +++ b/localwebsite/htdocs/assets/app.js @@ -1,4 +1,7 @@ -var ajax = { +(function() { +var RE_WHITESPACE = /[\t\r\n\f]/g + +window.ajax = { get: function(url, data) { if (typeof data == 'object') { var index = 0; @@ -35,28 +38,138 @@ var ajax = { } }; -function extend(a, b) { +window.extend = function(a, b) { return Object.assign(a, b); } -function ge(id) { +window.ge = function(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), - }; -})(); +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), +}; + +window.isTouchDevice = function() { + return 'ontouchstart' in window || navigator.msMaxTouchPoints; +} + +window.hasClass = function(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 + } +} + +window.addClass = function(el, name) { + if (!hasClass(el, name)) { + el.className = (el.className ? el.className + ' ' : '') + name; + return true + } + return false +} + +window.Cameras = { + hlsOptions: null, + hlsHost: null, + hlsProto: null, + debugVideoEvents: false, + + setupHls: function(video, name, useHls) { + var src = this.hlsProto + '://' + this.hlsHost + '/ipcam/' + name + '/live.m3u8'; + + // 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; + if (window.browserInfo.ios) + video.setAttribute('controls', 'controls'); + + video.src = src; + + var events = ['canplay']; + if (this.debugVideoEvents) + 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(cams, options, proto, host, debugVideoEvents) { + // this.cams = cams; + this.hlsOptions = options; + this.hlsProto = proto; + this.hlsHost = host; + this.debugVideoEvents = debugVideoEvents + + let 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 < cams.length; i++) { + var name = cams[i]; + var video = document.createElement('video'); + video.setAttribute('id', 'video-'+name); + document.getElementById('videos').appendChild(video); + + this.setupHls(video, name, useHls); + } + }, + + hasFallbackSupport: function() { + var video = document.createElement('video'); + return video.canPlayType('application/vnd.apple.mpegurl'); + }, +}; +})();
\ No newline at end of file diff --git a/localwebsite/templates-web/cams.twig b/localwebsite/templates-web/cams.twig index 4fc815d..0c61bc5 100644 --- a/localwebsite/templates-web/cams.twig +++ b/localwebsite/templates-web/cams.twig @@ -6,84 +6,9 @@ <div id="videos" class="camfeeds"></div> -<script> -function hasFallbackSupport() { - var video = document.createElement('video'); - return video.canPlayType('application/vnd.apple.mpegurl'); +{% js %} +if (isTouchDevice()) { + addClass(ge('videos'), 'is_mobile'); } - -function setupHls(video, name, useHls) { - var src = '{{ hls_proto }}://{{ hls_host }}/ipcam/'+name+'/live.m3u8'; - {% if hls_access_key %} - src += '?access_key={{ hls_access_key }}'; - {% endif %} - - // 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 = {{ hls_opts|json_encode|raw }}; - 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; - if (window.browserInfo.ios) - video.setAttribute('controls', 'controls'); - - video.src = src; - - var events = ['canplay']; - {% if video_events %} - events.push('canplay', 'canplaythrough', 'durationchange', 'ended', 'loadeddata', 'loadedmetadata', 'pause', 'play', 'playing', 'progress', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'waiting'); - {% endif %} - - for (var i = 0; i < events.length; i++) { - var evt = events[i]; - (function(evt, video, name) { - video.addEventListener(evt, function(e) { - {% if video_events %} - console.log(name + ': ' + evt, e); - {% endif %} - if (!window.browserInfo.ios && ['canplay', 'loadedmetadata'].includes(evt)) - video.play(); - }) - })(evt, video, name); - } - } -} - -function init() { - let useHls = Hls.isSupported(); - if (!useHls && !hasFallbackSupport()) { - alert('Neither HLS nor vnd.apple.mpegurl is not supported by your browser.'); - return; - } - - var cams = {{ cams|json_encode|raw }}; - for (var i = 0; i < cams.length; i++) { - var name = cams[i]; - var video = document.createElement('video'); - // video.setAttribute('height', '400'); - video.setAttribute('id', 'video-'+name); - document.getElementById('videos').appendChild(video); - - setupHls(video, name, useHls); - } -} - -init(); -</script>
\ No newline at end of file +Cameras.init({{ cams|json_encode|raw }}, {{ hls_opts|json_encode|raw }}, '{{ hls_proto }}', '{{ hls_host }}', {{ video_events ? 'true' : 'false' }}); +{% endjs %}
\ No newline at end of file |