From 25b6fa8488d24836e279e3918e4bae63ea91696d Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 19:21:20 +0300 Subject: [PATCH 01/10] Fix: Limit scope for "handleClick" (watch.js) --- web/skins/classic/views/js/watch.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 62f425bed..b34fe6b96 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -603,7 +603,10 @@ function handleClick(event) { streamReStart(oldId, newId); } else if (event.target.closest('#dvrControls')) { //Controls DVR cyclePause(); + } else if (!event.target.closest('#wrapperMonitor')) { + return; } + if (panZoomEnabled) { //event.preventDefault(); if (targetId) { From abc72ff7dc222d78907fa792fff170c388ddc56f Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 19:50:32 +0300 Subject: [PATCH 02/10] Fix: Include the file "includes/control_functions.php" only once (watch.php) --- web/skins/classic/views/watch.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index 3b28b4c39..cd6ad5782 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -354,6 +354,10 @@ echo htmlSelect('cyclePeriod', $cyclePeriodOptions, $period, array('id'=>'cycleP $monitorsExtraData = []; $monitorJanusUsed = false; $dataMonIdx=0; + if ($hasPtzControls) { + foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile ) + require_once $includeFile; + } foreach ($monitors as $m) { $monitorsExtraData[$m->Id()]['StreamHTML'] = $m->getStreamHTML($options); $monitorsExtraData[$m->Id()]['urlForAllEvents'] = "?view=events&page=1&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=Monitor&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D=%3D&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=".$m->Id()."&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Bsort_field%5D=StartDateTime&filter%5BQuery%5D%5Bskip_locked%5D=&filter%5BQuery%5D%5Blimit%5D=0"; @@ -362,8 +366,6 @@ echo htmlSelect('cyclePeriod', $cyclePeriodOptions, $period, array('id'=>'cycleP } $monitorsExtraData[$m->Id()]['ptzControls'] = ''; if ($hasPtzControls) { - foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile ) - require_once $includeFile; $ptzControls = ptzControls($m); $monitorsExtraData[$m->Id()]['ptzControls'] = $ptzControls; } From f40cf5866e577e699e3c4ce611e2fc9520d83242 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 20:31:36 +0300 Subject: [PATCH 03/10] Fix: addEventListener used after page load (skin.js) This will be more correct! This solves the problem https://forums.zoneminder.com/viewtopic.php?p=134573#p134573 I hope no other problems arise in connection with the code transfer. --- web/skins/classic/js/skin.js | 92 +++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index d6489b3e0..a68bcc1cc 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -60,49 +60,6 @@ function checkSize() { } } -// Polyfill for NodeList.prototype.forEach on IE. -if (window.NodeList && !NodeList.prototype.forEach) { - NodeList.prototype.forEach = Array.prototype.forEach; -} - -window.addEventListener("DOMContentLoaded", function onSkinDCL() { - document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) { - el.addEventListener("submit", function onSubmit(evt) { - if (!validateForm(this)) { - evt.preventDefault(); - } - }); - }); - - document.querySelectorAll(".zmlink").forEach(function(el) { - el.addEventListener("click", function onClick(evt) { - var el = this; - var url; - if ( el.hasAttribute("href") ) { - // - url = el.getAttribute("href"); - } else { - // buttons - url = el.getAttribute("data-url"); - } - evt.preventDefault(); - window.location.assign(url); - }); - }); - - document.querySelectorAll(".pillList a").forEach(function addOnClick(el) { - el.addEventListener("click", submitTab); - }); - - dataOnClickThis(); - dataOnClick(); - dataOnClickTrue(); - dataOnChangeThis(); - dataOnChange(); - dataOnInput(); - dataOnInputThis(); -}); - // 'data-on-click-this' calls the global function in the attribute value with the element when a click happens. function dataOnClickThis() { document.querySelectorAll("a[data-on-click-this], button[data-on-click-this], input[data-on-click-this], span[data-on-click-this]").forEach(function attachOnClick(el) { @@ -1161,4 +1118,51 @@ function loadFontFaceObserver() { }); } -loadFontFaceObserver(); +function initPage() { + // Polyfill for NodeList.prototype.forEach on IE. + if (window.NodeList && !NodeList.prototype.forEach) { + NodeList.prototype.forEach = Array.prototype.forEach; + } + + window.addEventListener("DOMContentLoaded", function onSkinDCL() { + document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) { + el.addEventListener("submit", function onSubmit(evt) { + if (!validateForm(this)) { + evt.preventDefault(); + } + }); + }); + + document.querySelectorAll(".zmlink").forEach(function(el) { + el.addEventListener("click", function onClick(evt) { + var el = this; + var url; + if ( el.hasAttribute("href") ) { + // + url = el.getAttribute("href"); + } else { + // buttons + url = el.getAttribute("data-url"); + } + evt.preventDefault(); + window.location.assign(url); + }); + }); + + document.querySelectorAll(".pillList a").forEach(function addOnClick(el) { + el.addEventListener("click", submitTab); + }); + + dataOnClickThis(); + dataOnClick(); + dataOnClickTrue(); + dataOnChangeThis(); + dataOnChange(); + dataOnInput(); + dataOnInputThis(); + }); + + loadFontFaceObserver(); +} + +$j( window ).on("load", initPage); From add8eb4be363c4dcfb6069e7573532e49a2f36ae Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 21:18:47 +0300 Subject: [PATCH 04/10] Temporarily added dataOnClick() when initializing the page (watch.js) --- web/skins/classic/views/js/watch.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index b34fe6b96..2b79bb3c2 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1198,6 +1198,7 @@ function initPage() { if (currentMonitor) { applyMonitorControllable(currentMonitor); } + dataOnClick(); } // initPage function watchFullscreen() { From 5e3bfbb392682dde2903b9ce305cb5e65299fa42 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 21:54:01 +0300 Subject: [PATCH 05/10] Call dataOnClick() when switching to new next camera (watch.js) Necessary because we change the DOM --- web/skins/classic/views/js/watch.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 2b79bb3c2..e51c6a259 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1062,6 +1062,7 @@ function streamReStart(oldId, newId) { applyMonitorControllable(currentMonitor); zmPanZoom.init(); loadFontFaceObserver(); + dataOnClick(); //document.getElementById('monitor').classList.remove('hidden-shift'); } From e874fd9c1f62a79e4d80456f29d1f2d2460bb588 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 22:33:20 +0300 Subject: [PATCH 06/10] Chore: code optimization (watch.js) --- web/skins/classic/views/js/watch.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index e51c6a259..be65d9017 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -973,6 +973,7 @@ function streamPrepareStart(monitor=null) { } }, 100); setButtonStateWatch('stopBtn', 'active'); + dataOnClick(); } function handleMouseEnter(event) { @@ -1062,7 +1063,6 @@ function streamReStart(oldId, newId) { applyMonitorControllable(currentMonitor); zmPanZoom.init(); loadFontFaceObserver(); - dataOnClick(); //document.getElementById('monitor').classList.remove('hidden-shift'); } @@ -1192,14 +1192,13 @@ function initPage() { //document.getElementById('monitor').classList.remove('hidden-shift'); changeObjectClass(); - streamPrepareStart(); const currentMonitor = monitorData.find((o) => { return parseInt(o["id"]) === monitorId; }); if (currentMonitor) { applyMonitorControllable(currentMonitor); } - dataOnClick(); + streamPrepareStart(); } // initPage function watchFullscreen() { From 6308ceaf0c94911994723db7b6ee146c6ff138b1 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 22:48:02 +0300 Subject: [PATCH 07/10] Update watch.js --- web/skins/classic/views/js/watch.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index be65d9017..757ef7cde 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1216,9 +1216,6 @@ function watchFullscreen() { } function watchAllEvents() { - const currentMonitor = monitorData.find((o) => { - return parseInt(o["id"]) === monitorId; - }); window.location.replace(currentMonitor.urlForAllEvents); } From 073bbfc31620838fdebcb12adcf480124a74dc8c Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 23:06:59 +0300 Subject: [PATCH 08/10] dataOnClick is called with a delay, because DOM change occurs (watch.js) --- web/skins/classic/views/js/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 2da92d48a..b855f40c3 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -974,7 +974,7 @@ function streamPrepareStart(monitor=null) { } }, 100); setButtonStateWatch('stopBtn', 'active'); - dataOnClick(); + setTimeout(dataOnClick, 100); } function handleMouseEnter(event) { From a4443bb0a77a73662d170811ae860194163810c7 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Tue, 11 Jun 2024 23:17:01 +0300 Subject: [PATCH 09/10] Update watch.js --- web/skins/classic/views/js/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index b855f40c3..2a4da1d82 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1060,8 +1060,8 @@ function streamReStart(oldId, newId) { streamMode = currentMonitor.streamMode; table.bootstrapTable('destroy'); - streamPrepareStart(currentMonitor); applyMonitorControllable(); + streamPrepareStart(currentMonitor); zmPanZoom.init(); loadFontFaceObserver(); //document.getElementById('monitor').classList.remove('hidden-shift'); From fe9cc6d2a7f7128df9b4934e5d6b583b004016c6 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Wed, 12 Jun 2024 00:14:44 +0300 Subject: [PATCH 10/10] Don't change skin.js now, it will cause problems in other places Additional research is required in a quiet environment. --- web/skins/classic/js/skin.js | 92 +++++++++++++++++------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index a68bcc1cc..d6489b3e0 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -60,6 +60,49 @@ function checkSize() { } } +// Polyfill for NodeList.prototype.forEach on IE. +if (window.NodeList && !NodeList.prototype.forEach) { + NodeList.prototype.forEach = Array.prototype.forEach; +} + +window.addEventListener("DOMContentLoaded", function onSkinDCL() { + document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) { + el.addEventListener("submit", function onSubmit(evt) { + if (!validateForm(this)) { + evt.preventDefault(); + } + }); + }); + + document.querySelectorAll(".zmlink").forEach(function(el) { + el.addEventListener("click", function onClick(evt) { + var el = this; + var url; + if ( el.hasAttribute("href") ) { + // + url = el.getAttribute("href"); + } else { + // buttons + url = el.getAttribute("data-url"); + } + evt.preventDefault(); + window.location.assign(url); + }); + }); + + document.querySelectorAll(".pillList a").forEach(function addOnClick(el) { + el.addEventListener("click", submitTab); + }); + + dataOnClickThis(); + dataOnClick(); + dataOnClickTrue(); + dataOnChangeThis(); + dataOnChange(); + dataOnInput(); + dataOnInputThis(); +}); + // 'data-on-click-this' calls the global function in the attribute value with the element when a click happens. function dataOnClickThis() { document.querySelectorAll("a[data-on-click-this], button[data-on-click-this], input[data-on-click-this], span[data-on-click-this]").forEach(function attachOnClick(el) { @@ -1118,51 +1161,4 @@ function loadFontFaceObserver() { }); } -function initPage() { - // Polyfill for NodeList.prototype.forEach on IE. - if (window.NodeList && !NodeList.prototype.forEach) { - NodeList.prototype.forEach = Array.prototype.forEach; - } - - window.addEventListener("DOMContentLoaded", function onSkinDCL() { - document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) { - el.addEventListener("submit", function onSubmit(evt) { - if (!validateForm(this)) { - evt.preventDefault(); - } - }); - }); - - document.querySelectorAll(".zmlink").forEach(function(el) { - el.addEventListener("click", function onClick(evt) { - var el = this; - var url; - if ( el.hasAttribute("href") ) { - // - url = el.getAttribute("href"); - } else { - // buttons - url = el.getAttribute("data-url"); - } - evt.preventDefault(); - window.location.assign(url); - }); - }); - - document.querySelectorAll(".pillList a").forEach(function addOnClick(el) { - el.addEventListener("click", submitTab); - }); - - dataOnClickThis(); - dataOnClick(); - dataOnClickTrue(); - dataOnChangeThis(); - dataOnChange(); - dataOnInput(); - dataOnInputThis(); - }); - - loadFontFaceObserver(); -} - -$j( window ).on("load", initPage); +loadFontFaceObserver();