diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 820a5d980..238eae2e7 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -2933,6 +2933,16 @@ our @options = ( type => $types{integer}, category => 'highband', }, + { + name => 'ZM_WEB_H_REFRESH_NAVBAR', + default => '5', + description => 'How often (in seconds) the navigation header should refresh itself', + help => q` + The navigation header contains the general status information about server load and storage space. + `, + type => $types{integer}, + category => 'highband', + }, { name => 'ZM_WEB_H_REFRESH_CYCLE', default => '10', @@ -3196,6 +3206,16 @@ our @options = ( `, category => 'medband', }, + { + name => 'ZM_WEB_M_REFRESH_NAVBAR', + default => '15', + description => 'How often (in seconds) the navigation header should refresh itself', + help => q` + The navigation header contains the general status information about server load and storage space. + `, + type => $types{integer}, + category => 'medband', + }, { name => 'ZM_WEB_M_REFRESH_CYCLE', default => '20', @@ -3459,6 +3479,16 @@ our @options = ( type => $types{integer}, category => 'lowband', }, + { + name => 'ZM_WEB_L_REFRESH_NAVBAR', + default => '35', + description => 'How often (in seconds) the navigation header should refresh itself', + help => q` + The navigation header contains the general status information about server load and storage space. + `, + type => $types{integer}, + category => 'lowband', + }, { name => 'ZM_WEB_L_REFRESH_CYCLE', default => '30', diff --git a/web/ajax/status.php b/web/ajax/status.php index 840f9e3a1..ba9c5f3a6 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -1,4 +1,8 @@ array( diff --git a/web/skins/classic/css/classic/views/event.css b/web/skins/classic/css/classic/views/event.css index 100f53266..dbcc30835 100644 --- a/web/skins/classic/css/classic/views/event.css +++ b/web/skins/classic/css/classic/views/event.css @@ -12,15 +12,17 @@ .alarmCue { background-color: #222222; - height: 1.5em; + height: 1.25em; text-align: left; margin: 0 auto 0 auto; + border-radius: 0 0 .3em .3em; } .alarmCue span { background-color:red; - height: 1.5em; + height: 100%; display: inline-block; + border-radius: 0; } span.noneCue { @@ -43,11 +45,6 @@ span.noneCue { padding: 2px; } -#eventVideo { - display: inline-block; - postion: relative; -} - #menuBar1 { width: 100%; padding: 3px 0; @@ -117,6 +114,11 @@ span.noneCue { float: right; } +#eventVideo { + display: inline-block; + position: relative; +} + #imageFeed { display: inline-block; position: relative; @@ -184,14 +186,16 @@ span.noneCue { #progressBar { position: relative; - top: -1.5em; - height: 1.5em; - margin: 0 auto -1.5em auto; + top: -1.25em; + height: 1.25em; + margin: 0 auto -1.25em auto; } #progressBar .progressBox { - height: 1.5em; + transition: width .1s; + height: 100%; background: rgba(170, 170, 170, .7); + border-radius: 0 0 .3em .3em; } #eventStills { @@ -223,6 +227,7 @@ span.noneCue { } #eventImagePanel { + display: none; position: absolute; top: 0; left: 0; @@ -267,7 +272,7 @@ span.noneCue { #eventImageNav { position: relative; - margin: 4px 0 0 0; + margin: 0 0 4px 0; } #eventImageNav input { @@ -276,20 +281,20 @@ span.noneCue { } #thumbsSliderPanel { - width: 400px; - margin: 4px auto 0; - background: #888888; - padding: 1px; + width: 80%; + margin: 0px auto 4px auto; } #thumbsSlider { - width: 400px; - height: 10px; - background: #dddddd; + width: 100%; + height: 1.25em; + position: relative; + top: -1.25em; + margin: 0 0 -1.25em 0; } #thumbsKnob { - width: 8px; - height: 10px; - background-color: #444444; + width: 1em; + height: 100%; + background-color: #999999; } diff --git a/web/skins/classic/css/classic/views/frame.css b/web/skins/classic/css/classic/views/frame.css index 85c8cd11c..c9cb1846c 100644 --- a/web/skins/classic/css/classic/views/frame.css +++ b/web/skins/classic/css/classic/views/frame.css @@ -1,33 +1,16 @@ #scaleControl { float: right; } + #controls { width: 80%; text-align: center; margin: 0 auto; + display: flex; + justify-content: space-between; } #controls a { width: 40px; margin-left: -20px; } - -#firstLink { - position: absolute; - left: 13%; -} - -#prevLink { - position: absolute; - left: 37%; -} - -#nextLink { - position: absolute; - left: 63%; -} - -#lastLink { - position: absolute; - left: 87%; -} diff --git a/web/skins/classic/css/classic/views/montage.css b/web/skins/classic/css/classic/views/montage.css index d2eb33ec2..ae56ebc9b 100644 --- a/web/skins/classic/css/classic/views/montage.css +++ b/web/skins/classic/css/classic/views/montage.css @@ -19,6 +19,10 @@ #monitors .alert { color: #ffa500; + margin: 0; + padding: 0; + border-radius: 0; + border: none; } #monitors .imageFeed { diff --git a/web/skins/classic/css/dark/skin.css b/web/skins/classic/css/dark/skin.css index 799a2ba7c..3bd2ad1e3 100644 --- a/web/skins/classic/css/dark/skin.css +++ b/web/skins/classic/css/dark/skin.css @@ -460,9 +460,9 @@ th.table-th-sort-rev span.table-th-sort-span { button, input[type=button], input[type=submit] { - background-color: #3498db; - color: #fff; - border-color: #3498db; + background-color: #444444; + color: #eeeeee; + border-color: #444444; text-transform: uppercase; font-weight: 200; padding: 5px 10px; @@ -472,7 +472,7 @@ input[type=submit] { button:hover, input[type=button]:hover, input[type=submit]:hover { - background-color: #34a2ee; + background-color: #555555; } @@ -482,9 +482,9 @@ button:disabled, input[disabled], input[type=button]:disabled, input[type=submit]:disabled { - color: #ffffff; - background-color: #aaaaaa; - border-color: #bbbbbb; + color: #888888; + background-color: #666666; + border-color: #666666; } /* @@ -534,8 +534,10 @@ input[type=submit]:disabled { margin-left: 0; } - .table-striped > tbody > tr:nth-of-type(2n+1) { - background: none; + background-color: #333333; } +.table-hover>tbody>tr:hover { + background-color: #444444; +} diff --git a/web/skins/classic/css/dark/views/event.css b/web/skins/classic/css/dark/views/event.css index b206535d4..a156c2438 100644 --- a/web/skins/classic/css/dark/views/event.css +++ b/web/skins/classic/css/dark/views/event.css @@ -12,25 +12,23 @@ .alarmCue { background-color: #222222; - height: 1.5em; + height: 1.25em; text-align: left; margin: 0 auto 0 auto; + border-radius: 0 0 .3em .3em; } .alarmCue span { background-color:red; - height: 1.5em; + height: 100%; display: inline-block; + border-radius: 0; } span.noneCue { background: none; } -#eventVideo { - display: inline-block; -} - #dataBar { width: 100%; margin: 2px auto; @@ -99,6 +97,10 @@ span.noneCue { visibility: hidden; } +#eventVideo { + display: inline-block; +} + #imageFeed { display: inline-block; position: relative; @@ -166,14 +168,16 @@ span.noneCue { #progressBar { position: relative; - top: -1.5em; - height: 1.5em; - margin: 0 auto -1.5em auto; + top: -1.25em; + height: 1.25em; + margin: 0 auto -1.25em auto; } #progressBar .progressBox { - height: 1.5em; + transition: width .1s; + height: 100%; background: rgba(170, 170, 170, .7); + border-radius: 0 0 .3em .3em; } #eventStills { @@ -206,6 +210,7 @@ span.noneCue { } #eventImagePanel { + display: none; position: absolute; top: 0; left: 0; @@ -250,7 +255,7 @@ span.noneCue { #eventImageNav { position: relative; - margin: 4px 0 0 0; + margin: 0 0 4px 0; } #eventImageNav input { @@ -259,25 +264,20 @@ span.noneCue { } #thumbsSliderPanel { - width: 400px; - margin: 4px auto 0; - background: #888888; - padding: 1px; + width: 80%; + margin: 0px auto 4px auto; } #thumbsSlider { - width: 400px; - height: 10px; - background: #dddddd; -} - -#eventVideo { - display: inline-block; + width: 100%; + height: 1.25em; position: relative; + top: -1.25em; + margin: 0 0 -1.25em 0; } #thumbsKnob { - width: 8px; - height: 10px; - background-color: #444444; + width: 1em; + height: 100%; + background-color: #999999; } diff --git a/web/skins/classic/css/dark/views/frame.css b/web/skins/classic/css/dark/views/frame.css index 85c8cd11c..c9cb1846c 100644 --- a/web/skins/classic/css/dark/views/frame.css +++ b/web/skins/classic/css/dark/views/frame.css @@ -1,33 +1,16 @@ #scaleControl { float: right; } + #controls { width: 80%; text-align: center; margin: 0 auto; + display: flex; + justify-content: space-between; } #controls a { width: 40px; margin-left: -20px; } - -#firstLink { - position: absolute; - left: 13%; -} - -#prevLink { - position: absolute; - left: 37%; -} - -#nextLink { - position: absolute; - left: 63%; -} - -#lastLink { - position: absolute; - left: 87%; -} diff --git a/web/skins/classic/css/dark/views/montage.css b/web/skins/classic/css/dark/views/montage.css index 85306393d..005569117 100644 --- a/web/skins/classic/css/dark/views/montage.css +++ b/web/skins/classic/css/dark/views/montage.css @@ -16,6 +16,10 @@ #monitors .alert { color: #ffa500; + margin: 0; + padding: 0; + border-radius: 0; + border: none; } #monitors .imageFeed { diff --git a/web/skins/classic/css/flat/views/event.css b/web/skins/classic/css/flat/views/event.css index 41cad61dd..30758b573 100644 --- a/web/skins/classic/css/flat/views/event.css +++ b/web/skins/classic/css/flat/views/event.css @@ -12,15 +12,17 @@ .alarmCue { background-color: #222222; - height: 1.5em; + height: 1.25em; text-align: left; margin: 0 auto 0 auto; + border-radius: 0 0 .3em .3em; } .alarmCue span { background-color:red; - height: 1.5em; + height: 100%; display: inline-block; + border-radius: 0; } span.noneCue { @@ -50,7 +52,6 @@ span.noneCue { clear: both; } - #menuBar1 #nameControl { float: left; } @@ -85,15 +86,6 @@ span.noneCue { float: right; text-align: right; } -#menuBar1:after, -#menuBar2:after { - content: "."; - display: block; - height: 0; - font-size: 0; - clear: both; - visibility: hidden; -} #menuBar1:after, #menuBar2:after { @@ -104,6 +96,12 @@ span.noneCue { clear: both; visibility: hidden; } + +#eventVideo { + display: inline-block; + position: relative; +} + #imageFeed { display: inline-block; position: relative; @@ -177,14 +175,16 @@ span.noneCue { #progressBar { position: relative; - top: -1.5em; - height: 1.5em; - margin: 0 auto -1.5em auto; + top: -1.25em; + height: 1.25em; + margin: 0 auto -1.25em auto; } #progressBar .progressBox { - height: 1.5em; + transition: width .1s; + height: 100%; background: rgba(170, 170, 170, .7); + border-radius: 0 0 .3em .3em; } #eventStills { @@ -217,6 +217,7 @@ span.noneCue { } #eventImagePanel { + display: none; position: absolute; top: 0; left: 0; @@ -261,7 +262,7 @@ span.noneCue { #eventImageNav { position: relative; - margin: 4px 0 0 0; + margin: 0 0 4px 0; } #eventImageNav input { @@ -270,82 +271,20 @@ span.noneCue { } #thumbsSliderPanel { - width: 400px; - margin: 4px auto 0; - background: #888888; - padding: 1px; + width: 80%; + margin: 0px auto 4px auto; } #thumbsSlider { - width: 400px; - height: 10px; - background: #dddddd; + width: 100%; + height: 1.25em; + position: relative; + top: -1.25em; + margin: 0 0 -1.25em 0; } #thumbsKnob { - width: 8px; - height: 10px; - background-color: #444444; -} -#eventVideo { - display: inline-block; - position: relative; -} - -#video-controls { - position: absolute; - bottom: 0; - left: 0; - right: 0; - padding: 5px; - opacity: 0; - -webkit-transition: opacity .3s; - -moz-transition: opacity .3s; - -o-transition: opacity .3s; - -ms-transition: opacity .3s; - transition: opacity .3s; - background-image: linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%); - background-image: -o-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%); - background-image: -moz-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%); - background-image: -webkit-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%); - background-image: -ms-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%); - - background-image: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0.13, rgb(3,113,168)), - color-stop(1, rgb(0,136,204)) - ); -} - -#eventVideo:hover #video-controls { - opacity: .9; -} - -button { - background: rgba(0,0,0,.5); - border: 0; - color: #EEE; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - -o-border-radius: 3px; - border-radius: 3px; - padding: 0; -} - -button:hover { - cursor: pointer; -} - -#seekbar { - width: 360px; - border: 0; - padding: 0; -} - -#volume-bar { - width: 60px; - border: 0; - padding: 0; + width: 1em; + height: 100%; + background-color: #999999; } diff --git a/web/skins/classic/css/flat/views/frame.css b/web/skins/classic/css/flat/views/frame.css index 9e3e94da1..c9cb1846c 100644 --- a/web/skins/classic/css/flat/views/frame.css +++ b/web/skins/classic/css/flat/views/frame.css @@ -6,29 +6,11 @@ width: 80%; text-align: center; margin: 0 auto; + display: flex; + justify-content: space-between; } #controls a { width: 40px; margin-left: -20px; } - -#firstLink { - position: absolute; - left: 13%; -} - -#prevLink { - position: absolute; - left: 37%; -} - -#nextLink { - position: absolute; - left: 63%; -} - -#lastLink { - position: absolute; - left: 87%; -} diff --git a/web/skins/classic/includes/config.php b/web/skins/classic/includes/config.php index 763a2b8cc..6242794e1 100644 --- a/web/skins/classic/includes/config.php +++ b/web/skins/classic/includes/config.php @@ -45,7 +45,7 @@ $scales = array( '12.5' => '1/8x', ); -if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'event' ? '' : 'auto']); //Remove the option we aren't using on montage or event +if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'montage' ? 'auto' : '']); //Only use fixed width/Height on montage $bandwidth_options = array( 'high' => translate('High'), @@ -56,6 +56,7 @@ $bandwidth_options = array( switch ( $_COOKIE['zmBandwidth'] ) { case 'high' : { define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_H_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_H_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_H_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window @@ -73,6 +74,7 @@ switch ( $_COOKIE['zmBandwidth'] ) { break; } case 'medium' : { define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_M_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_M_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_M_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window @@ -90,6 +92,7 @@ switch ( $_COOKIE['zmBandwidth'] ) { break; } case 'low' : { define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_L_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_L_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_L_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 450cf63b3..b2e6d17c9 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -159,26 +159,24 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) { - -
+ +
@@ -277,9 +279,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?> echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%'; ?> -
- -
+ + + container.innerWidth()) { + newWidth = container.innerWidth(); + newHeight = newWidth / ratio; + } + let autoScale = Math.round(newWidth / baseWidth * SCALE_BASE); + let scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get(); + scales.shift(); + let closest; + $j(scales).each(function () { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values. + if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) { + closest = this.valueOf(); + } + }); + autoScale = closest; + return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale}; +} diff --git a/web/skins/classic/js/skin.js.php b/web/skins/classic/js/skin.js.php index b5797a97f..f726f06a5 100644 --- a/web/skins/classic/js/skin.js.php +++ b/web/skins/classic/js/skin.js.php @@ -26,6 +26,8 @@ ?> var AJAX_TIMEOUT = ; +var navBarRefresh = ; + var currentView = ''; var thisUrl = ""; var skinPath = ""; diff --git a/web/skins/classic/js/video-js-skin.css b/web/skins/classic/js/video-js-skin.css index f83729e00..71ee696bf 100644 --- a/web/skins/classic/js/video-js-skin.css +++ b/web/skins/classic/js/video-js-skin.css @@ -1,5 +1,6 @@ .vjs-tech { pointer-events: none; + transition: transform .25s; } .vjs-captions-button { diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 41c119967..c91102254 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -184,7 +184,7 @@ Warning("Streamsrc: $streamSrc"); } } // end if stream method ?> -
+
@@ -224,6 +224,13 @@ Warning("Streamsrc: $streamSrc");
+
+
+
+
+
+
+
@@ -234,12 +241,6 @@ Warning("Streamsrc: $streamSrc");
-
-
-
-
-
-
Type()=='Alarm'; if ( isset( $_REQUEST['scale'] ) ) { - $scale = validInt($_REQUEST['scale']); + $scale = $_REQUEST['scale']; } else if ( isset( $_COOKIE['zmWatchScale'.$Monitor->Id()] ) ) { $scale = $_COOKIE['zmWatchScale'.$Monitor->Id()]; } else if ( isset( $_COOKIE['zmWatchScale'] ) ) { diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 95460a8f1..702bbc3c7 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -40,8 +40,6 @@ function vjsReplay() { } } -$j.ajaxSetup ({timeout: AJAX_TIMEOUT }); //sets timeout for all getJSON. - var cueFrames = null; //make cueFrames availaible even if we don't send another ajax query function initialAlarmCues (eventId) { @@ -50,13 +48,13 @@ function initialAlarmCues (eventId) { function setAlarmCues (data) { cueFrames = data.frames; - alarmSpans = renderAlarmCues(); + alarmSpans = renderAlarmCues(vid ? $j("#videoobj") : $j("#evtStream"));//use videojs width or zms width $j(".alarmCue").html(alarmSpans); } -function renderAlarmCues () { +function renderAlarmCues (containerEl) { if (cueFrames) { - var cueRatio = (vid ? $j("#videoobj").width() : $j("#evtStream").width()) / (cueFrames[cueFrames.length - 1].Delta * 100);//use videojs width or zms width + var cueRatio = containerEl.width() / (cueFrames[cueFrames.length - 1].Delta * 100); var minAlarm = Math.ceil(1/cueRatio); var spanTimeStart = 0; var spanTimeEnd = 0; @@ -134,45 +132,21 @@ function setButtonState( element, butClass ) { } } -var resizeTimer; - -function endOfResize(e) { - clearTimeout(resizeTimer); - resizeTimer = setTimeout(changeScale, 250); -} - -function scaleToFit () { - $j(window).on('resize', endOfResize) //set delayed scaling when Scale to Fit is selected - let ratio = eventData.Width/eventData.Height; - let container = $j('#content'); - let feed = $j(vid ? '#videoobj' : '#evtStream'); - let viewPort = $j(window); - let newHeight = viewPort.height() - (container.outerHeight(true) - feed.outerHeight(true)); - let newWidth = ratio * newHeight; - if (newWidth > container.innerWidth()) { - newWidth = container.innerWidth(); - newHeight = newWidth / ratio; - } - let autoScale = Math.round(newWidth / eventData.Width * SCALE_BASE); - let scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get(); - scales.shift(); - let closest = null; - $j(scales).each(function () { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values. - if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) { - closest = this.valueOf(); - } - }); - autoScale = closest; - return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale}; -} - function changeScale() { let scale = $j('#scale').val(); - let newWidth = null; - let newHeight = null; - let autoScale = null; + let newWidth; + let newHeight; + let autoScale; + let eventViewer; + let alarmCue = $j('div.alarmCue'); + let bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus'); + if (streamMode == 'stills') { + eventViewer = $j('#eventThumbs'); + } else { + eventViewer = $j(vid ? '#videoobj' : '#evtStream'); + } if (scale == "auto") { - let newSize = scaleToFit(); + let newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl); newWidth = newSize.width; newHeight = newSize.height; autoScale = newSize.autoScale; @@ -181,16 +155,18 @@ function changeScale() { newWidth = eventData.Width * scale / SCALE_BASE; newHeight = eventData.Height * scale / SCALE_BASE; } - let alarmCue = $j('div.alarmCue'); - let eventViewer = $j(vid ? '#videoobj' : '#evtStream') - eventViewer.width(newWidth); + if (!(streamMode == 'stills')) eventViewer.width(newWidth); //stills handles its own width eventViewer.height(newHeight); if ( !vid ) { // zms needs extra sizing streamScale(scale == "auto" ? autoScale : scale); - alarmCue.width(newWidth); drawProgressBar(); } - alarmCue.html(renderAlarmCues());//just re-render alarmCues. skip ajax call + if (streamMode == 'stills') { + slider.autosize(); + alarmCue.html(renderAlarmCues($j('#thumbsSliderPanel'))); + } else { + alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call + } if (scale == "auto") { Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365}); }else{ @@ -505,6 +481,7 @@ function streamQuery() { var slider = null; var scroll = null; +var currEventId = null; var CurEventDefVideoPath = null; function getEventResponse( respObj, respText ) { @@ -698,13 +675,11 @@ function resetEventStills() { fid = 1; else if ( fid > eventData.Frames ) fid = eventData.Frames; - checkFrames( eventData.Id, fid ); + checkFrames( eventData.Id, fid, ($j('#eventImagePanel').css('display')=='none'?'':'true')); scroll.toElement( 'eventThumb'+fid ); } } ).set( 0 ); } - if ( $('eventThumbs').getStyle( 'height' ).match( /^\d+/ ) < (parseInt(eventData.Height)+80) ) - $('eventThumbs').setStyle( 'height', ($j(vid ? '#videoobj' : '#evtStream').height())+'px' ); } function getFrameResponse( respObj, respText ) { @@ -893,6 +868,7 @@ function showStream() { $('streamEvent').addClass( 'hidden' ); streamMode = 'video'; + if (scale == 'auto') changeScale(); } function showStills() { @@ -924,6 +900,7 @@ function showStills() { ); } resetEventStills(); + if (scale == 'auto') changeScale(); } function showFrameStats() { diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index 4187b4be1..dbdc5c514 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -48,6 +48,7 @@ var canEditEvents = ; var streamTimeout = ; var canStreamNative = ; +var streamMode = ''; // // Strings diff --git a/web/skins/classic/views/js/frame.js b/web/skins/classic/views/js/frame.js index 0705032bc..bff17a7ac 100644 --- a/web/skins/classic/views/js/frame.js +++ b/web/skins/classic/views/js/frame.js @@ -1,15 +1,35 @@ function changeScale() { - var scale = $('scale').get('value'); - var img = $('frameImg'); - if ( img ) { - var baseWidth = $('base_width').value; - var baseHeight = $('base_height').value; - var newWidth = ( baseWidth * scale ) / SCALE_BASE; - var newHeight = ( baseHeight * scale ) / SCALE_BASE; + let scale = $j('#scale').val(); + let img = $j('#frameImg'); + let controlsLinks = { + next: $j('#nextLink'), + prev: $j('#prevLink'), + first: $j('#firstLink'), + last: $j('#lastLink') + } - img.style.width = newWidth + "px"; - img.style.height = newHeight + "px"; + if (img) { + let baseWidth = $j('#base_width').val(); + let baseHeight = $j('#base_height').val(); + if (scale == "auto") { + let newSize = scaleToFit(baseWidth, baseHeight, img, $j('#controls')); + newWidth = newSize.width; + newHeight = newSize.height; + autoScale = newSize.autoScale; + } else { + $j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active + newWidth = baseWidth * scale / SCALE_BASE; + newHeight = baseHeight * scale / SCALE_BASE; + } + img.css('width', newWidth + "px"); + img.css('height', newHeight + "px"); } Cookie.write( 'zmWatchScale', scale, { duration: 10*365 } ); + $j.each(controlsLinks, function(k, anchor) { //Make frames respect scale choices + anchor.prop('href', anchor.prop('href').replace(/scale=.*&/, 'scale=' + scale + '&')); + + }); } +if (scale == "auto") $j(document).ready(changeScale); + diff --git a/web/skins/classic/views/js/frame.js.php b/web/skins/classic/views/js/frame.js.php index dff39cdab..3964ef436 100644 --- a/web/skins/classic/views/js/frame.js.php +++ b/web/skins/classic/views/js/frame.js.php @@ -1,2 +1,3 @@ +var scale = ""; var SCALE_BASE = ; diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 57ad9d86c..6f33a97db 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -25,8 +25,19 @@ function showPtzControls() { function changeScale() { var scale = $('scale').get('value'); - var newWidth = ( monitorWidth * scale ) / SCALE_BASE; - var newHeight = ( monitorHeight * scale ) / SCALE_BASE; + var newWidth; + var newHeight; + if (scale == "auto") { + let newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus')); + newWidth = newSize.width; + newHeight = newSize.height; + autoScale = newSize.autoScale; + } else { + $j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active + newWidth = monitorWidth * scale / SCALE_BASE; + newHeight = monitorHeight * scale / SCALE_BASE; + } + Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } ); @@ -36,7 +47,7 @@ function changeScale() { streamImg.style.width = newWidth + "px"; streamImg.style.height = newHeight + "px"; - streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+scale); + streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale)); } else { console.error("No element found for liveStream."); } @@ -655,6 +666,7 @@ function initPage() { if ( refreshApplet && appletRefreshTime ) appletRefresh.delay( appletRefreshTime*1000 ); + if (scale == "auto") changeScale(); } // Kick everything off diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index 35a2debca..c0c8ab590 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -50,7 +50,7 @@ var monitorWidth = Width() ?>; var monitorHeight = Height() ?>; var monitorUrl = 'Server()->Url() ) ?>'; -var scale = ; +var scale = ''; var statusRefreshTimeout = ; var eventsRefreshTimeout = ; diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index ea2e0a588..30f7d0420 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -78,7 +78,7 @@ if ( isset($_COOKIE['zmMontageLayout']) ) { $options = array(); $Layout = ''; $Positions = ''; -if ( $layout_id ) { +if ( $layout_id and is_numeric($layout_id) and isset($layoutsById[$layout_id]) ) { $Layout = $layoutsById[$layout_id]; $Positions = json_decode( $Layout->Positions(), true ); }