diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 62adc22b0..450518481 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -44,17 +44,20 @@ $cpus = cpu_list(); _(Uptime)_ - + - - - - - - - - + +
+ + + + + + + + +
@@ -66,15 +69,6 @@ $('.title').append(""); - -function resize() { - $('#docker_list').height(Math.max(window.innerHeight-340,330)); - $('#docker_containers thead,#docker_containers tbody').removeClass('fixed'); - $('#docker_containers thead tr th').each(function(){$(this).width($(this).width());}); - $('#docker_containers tbody tr td').each(function(){$(this).width($(this).width());}); - $('#docker_containers thead,#docker_containers tbody').addClass('fixed'); -} - function resetSorting() { if ($.cookie('lockbutton')==null) return; $('input[type=button]').prop('disabled',true); @@ -146,10 +140,6 @@ function loadlist(init) { } }); $('head').append(' @@ -57,10 +58,15 @@ foreach($uri as $more) { $language = array_merge($language,unserialize(file_get_contents($store))); } } - -echo "
"; -show_map("Tasks", 1); -show_map("Buttons", 1); -echo "
"; ?> - + +
+ +
+ +
+ +
diff --git a/emhttp/plugins/dynamix/Processes.page b/emhttp/plugins/dynamix/Processes.page index 5b6223110..6abcfe81f 100644 --- a/emhttp/plugins/dynamix/Processes.page +++ b/emhttp/plugins/dynamix/Processes.page @@ -17,16 +17,19 @@ Tag="cogs" ?> -",shell_exec('ps -aux'),""; -?> - + +
+ +
+ +
diff --git a/emhttp/plugins/dynamix/Syslog.page b/emhttp/plugins/dynamix/Syslog.page index 43cb18f73..f68208c03 100644 --- a/emhttp/plugins/dynamix/Syslog.page +++ b/emhttp/plugins/dynamix/Syslog.page @@ -3,7 +3,7 @@ Title="System Log" Icon="icon-log" Tag="list" --- - -"; - foreach ($logs as $file) $select[] = mk_option(1,$file,basename($file)); - $select[] = ""; + // add syslog to front of logs array + array_unshift($logs, $log); + $select[] = ""; } $select = implode($select); ?> @@ -85,11 +87,6 @@ function toggle(checked) { highlight(checked,'L'); $('span.label input[type=checkbox]').not('.ctrl').prop('checked',checked); } - -function resize() { - $('pre.up').height(Math.max(window.innerHeight-320,330)); -} - function showLog(log) { logfile = log; @@ -141,22 +138,27 @@ $(function() { showLog(logfile); } }); - - resize(); - $(window).bind('resize',function(){resize();}); - showLog(logfile); + + + fillAvailableHeight({ + targetElementSelector: '.js-fill-available-height', + elementSelectorsForHeight: [ + '.js-syslog-controls', + '.js-syslog-actions', + ], + }); + }); -// $('.title .right').append(""); -
+
@@ -217,10 +219,10 @@ $(function() {
-

+

 
-
+
-
\ No newline at end of file +
diff --git a/emhttp/plugins/dynamix/Vars.page b/emhttp/plugins/dynamix/Vars.page index 55b9d5c21..7fce7fb4f 100644 --- a/emhttp/plugins/dynamix/Vars.page +++ b/emhttp/plugins/dynamix/Vars.page @@ -15,23 +15,28 @@ Tag="code" * all copies or substantial portions of the Software. */ ?> - - - getenv('http_proxy'), 'no_proxy' => getenv('no_proxy')]; -echo "
",htmlspecialchars(print_r($globals,true)),"
"; ?> - + + + + +
+ +
+ +
diff --git a/emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php b/emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php index 4215ffc51..8b14cbf57 100644 --- a/emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php +++ b/emhttp/plugins/dynamix/include/DefaultPageLayout/BodyInlineJS.php @@ -446,4 +446,128 @@ function nchanFocusStop(banner=true) { } } + +/** + * Calculates and sets the height of a target element to fill the available viewport space. + * + * This function dynamically resizes an element to occupy the remaining vertical space + * after accounting for other page elements like headers, footers, controls, and their + * margins/padding. Useful for creating full-height scrollable content areas. + * + * The function includes default elements that are commonly present on pages: + * - elementsForHeight: '#header', '#menu', '#footer' (plus any additional provided) + * - elementsForSpacing: '.displaybox' (plus any additional provided) + * + * @param {Object} params - Configuration object for height calculation + * @param {string} [params.targetElementSelector='.js-fill-available-height'] - CSS selector for the element to resize + * @param {string[]} [params.elementSelectorsForHeight=[]] - Additional CSS selectors for elements + * whose full height (including margins) should be subtracted from available space. + * These are added to the default selectors: '#header', '#menu', '#footer' + * @param {string[]} [params.elementSelectorsForSpacing=[]] - Additional CSS selectors for elements + * whose spacing (margins and padding only) should be subtracted from available space. + * These are added to the default selector: '.displaybox' + * @param {number} [params.minHeight=330] - Minimum height in pixels for the target element + * @param {number} [params.manualSpacingOffset=10] - Additional pixels to subtract for manual spacing + * + * @example + * // Use with default parameters - targets '.js-fill-available-height' + * fillAvailableHeight(); + * + * @example + * // Custom configuration with additional elements + * // MUST BE USED IN JQUERY ON READY + * $(function() { // or $(document).ready(function() { + * fillAvailableHeight({ + * targetElementSelector: '.my-content', + * elementSelectorsForHeight: ['.my-controls', '.my-actions'], + * elementSelectorsForSpacing: ['.my-content'], + * minHeight: 500, + * manualSpacingOffset: 20 + * }); + * }); + */ +function fillAvailableHeight(params = { // default params + targetElementSelector: '.js-fill-available-height', + elementSelectorsForHeight: [], + elementSelectorsForSpacing: [], + minHeight: 330, + manualSpacingOffset: 10, +}) { + const minHeight = params.minHeight || 330; + + // default elementsForHeight + const elementsForHeight = [ + '#header', + '#menu', + '#footer', + '.title', + ...(params.elementSelectorsForHeight ? params.elementSelectorsForHeight : []), + ]; + + // elements with a height and margin we want to subtract from the target height + let targetHeight = window.innerHeight - elementsForHeight.reduce((acc, selector) => { + const element = document.querySelector(selector); + + if (!element) { + return acc; + } + + const computedStyle = getComputedStyle(element); + const height = element.offsetHeight; + const marginTop = parseFloat(computedStyle.marginTop) || 0; + const marginBottom = parseFloat(computedStyle.marginBottom) || 0; + // we don't need to calculate padding because it's already included in the height + const totalForElement = height + marginTop + marginBottom; + + return acc + totalForElement; + }, 0); + + // elements with spacing that we want to subtract from the target height, but not their actual height. + const elementsForSpacing = [ + '#displaybox', + ...(params.targetElementSelector ? [params.targetElementSelector] : []), + ...(params.elementSelectorsForSpacing ? params.elementSelectorsForSpacing : []), + ]; + + targetHeight -= elementsForSpacing.reduce((acc, selector) => { + const element = document.querySelector(selector); + + if (!element) { + return acc; + } + + const computedStyle = getComputedStyle(element); + const marginTop = parseFloat(computedStyle.marginTop) || 0; + const marginBottom = selector !== '#displaybox' ? parseFloat(computedStyle.marginBottom) || 0 : 0; + const paddingTop = parseFloat(computedStyle.paddingTop) || 0; + const paddingBottom = selector !== '#displaybox' ? parseFloat(computedStyle.paddingBottom) || 0 : 0; + // we don't want to subtract paddingBottom or marginBottom for #displaybox b/c it adds unnecessary spacing in the calculations + // b/c the paddingBottom is accounting for the fixed footer. + + const totalForElement = marginTop + marginBottom + paddingTop + paddingBottom; + + return acc + totalForElement; + }, 0); + + // subtract addtional spacing from the target height to provide spacing between the actions & the footer + targetHeight -= params.manualSpacingOffset || 10; + + const finalHeight = Math.max(targetHeight, minHeight); + + $(params.targetElementSelector).height(finalHeight); + + // Set up resize listener to call itself with same params + // Remove existing listener first to avoid duplicates + if (window.fillAvailableHeightResizeHandler) { + window.removeEventListener('resize', window.fillAvailableHeightResizeHandler); + } + + // Create debounced handler that calls this function with same params + window.fillAvailableHeightResizeHandler = debounce(function() { + fillAvailableHeight(params); + }, 150); + + // Add the new listener + window.addEventListener('resize', window.fillAvailableHeightResizeHandler); +} diff --git a/emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php b/emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php index 3a7c5e185..5a7f2bd89 100644 --- a/emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php +++ b/emhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php @@ -562,4 +562,12 @@ $.ajaxPrefilter(function(s, orig, xhr){ } setTimerReload(); + +function debounce(func, wait = 300) { + let timeout; + return function(...args) { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; +} diff --git a/emhttp/plugins/dynamix/sheets/Syslog.css b/emhttp/plugins/dynamix/sheets/Syslog.css index a418409f7..11ce7c2b8 100644 --- a/emhttp/plugins/dynamix/sheets/Syslog.css +++ b/emhttp/plugins/dynamix/sheets/Syslog.css @@ -6,8 +6,6 @@ input#max { display: flex; justify-content: space-between; align-items: center; - gap: 10px; - margin-bottom: 10px; box-sizing: border-box; * {