PHP Classes

File: templates/shells/bbs-menu/main-menu-ansi.twig

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   templates/shells/bbs-menu/main-menu-ansi.twig   Download  
File: templates/shells/bbs-menu/main-menu-ansi.twig
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 5,950 bytes
 

Contents

Class file image Download
{# ANSI art menu variant for BBS shell #} {% if shell_art_content %} <div class="mb-3"> {# ANSI art is 80 columns wide at a monospace font size ? too wide for mobile. We wrap it in an overflow:hidden container and use JS to apply a CSS transform: scale() so it shrinks proportionally to fit the viewport. On desktop the art renders at natural size. #} <div class="ansi-art-wrapper d-flex justify-content-center" id="ansiArtWrapper" style="cursor:pointer;"> <pre class="ansi-art" id="shellMenuAnsi" data-ansi-size="{{ appearance.shell.bbs_menu.ansi_size|default('80x25')|e('html_attr') }}" style="display:inline-block;">{{ shell_art_content }}</pre> </div> {# Shortcut links ? hidden by default, revealed when the user clicks/taps the ANSI art above. Using display:none (not a Bootstrap breakpoint class) so it never auto-shows based on viewport width alone. #} {% set menuItems = bbs_menu_items %} <div id="ansiTouchLinks" class="mt-3" style="display:none;"> <div class="list-group"> {% for item in menuItems %} <a href="{{ item.url | e }}" class="list-group-item list-group-item-action d-flex align-items-center gap-2 py-3{% if item.url == '/files' %} file-menu-link{% endif %}"> <span class="badge bg-primary fs-6" style="min-width:2rem;">{{ item.key | upper | e }}</span> <i class="fas fa-{{ item.icon | default('circle') | e }} text-primary{% if item.url == '/files' %} file-menu-icon{% endif %}"></i> {{ item.label | e }} </a> {% endfor %} </div> </div> </div> <script> (function() { function resolveAnsiCanvas(size) { switch (size) { case '132x24': return { cols: 132, rows: 24, fitViewport: false }; case '132x43': return { cols: 132, rows: 43, fitViewport: false }; case '132x50': return { cols: 132, rows: 50, fitViewport: false }; case 'full': return { cols: 132, rows: 50, fitViewport: true }; case '80x25': default: return { cols: 80, rows: 25, fitViewport: false }; } } function scaleAnsiArt() { var pre = document.getElementById('shellMenuAnsi'); if (!pre) return; var wrapper = pre.closest('.ansi-art-wrapper'); if (!wrapper) return; var ansiSize = pre.dataset.ansiSize || '80x25'; var canvas = resolveAnsiCanvas(ansiSize); // Reset any previous scaling pre.style.fontSize = ''; pre.style.transform = 'scale(1)'; pre.style.transformOrigin = 'top center'; pre.style.position = ''; pre.style.left = ''; pre.style.top = ''; wrapper.style.height = ''; wrapper.style.position = ''; wrapper.style.overflow = ''; var isMobile = window.matchMedia('(max-width: 767.98px)').matches; var targetWidth = isMobile ? Math.floor(window.innerWidth * 0.99) : wrapper.clientWidth; var viewportPadding = isMobile ? 24 : 48; var wrapperTop = wrapper.getBoundingClientRect().top; var targetHeight = Math.max(0, window.innerHeight - wrapperTop - viewportPadding); var naturalWidth = pre.scrollWidth; var naturalHeight = pre.scrollHeight; if (targetWidth <= 0 || naturalWidth <= 0 || naturalHeight <= 0) { return; } var widthScale = targetWidth / naturalWidth; var heightScale = targetHeight > 0 ? (targetHeight / naturalHeight) : widthScale; var scale; if (canvas.fitViewport) { scale = Math.min(widthScale, heightScale); } else if (ansiSize === '80x25') { scale = 1; if (isMobile && targetWidth > 0 && naturalWidth > targetWidth) { scale = targetWidth / naturalWidth; } } else { var baselineScale = Math.min(80 / canvas.cols, 25 / canvas.rows); scale = baselineScale; if (isMobile && targetWidth > 0) { scale = Math.min(scale, widthScale); } } if (scale > 0 && Math.abs(scale - 1) > 0.0001) { wrapper.style.position = 'relative'; wrapper.style.overflow = 'hidden'; pre.style.position = 'absolute'; pre.style.left = '50%'; pre.style.top = '0'; if (canvas.fitViewport) { pre.style.transform = 'translateX(-50%) scale(' + scale.toFixed(4) + ')'; wrapper.style.height = Math.max(1, Math.floor(naturalHeight * scale)) + 'px'; } else { pre.style.transform = 'translateX(-50%) scale(' + scale.toFixed(4) + ')'; wrapper.style.height = Math.max(1, Math.floor(naturalHeight * scale)) + 'px'; } } else if (!canvas.fitViewport) { wrapper.style.height = Math.max(1, naturalHeight) + 'px'; } } // Run after ANSI rendering (which happens in a separate ready handler) $(document).ready(function() { // Small delay so the ANSI renderer has run first setTimeout(scaleAnsiArt, 50); // Clicking/tapping the ANSI art toggles the shortcut link list var wrapper = document.getElementById('ansiArtWrapper'); var links = document.getElementById('ansiTouchLinks'); if (wrapper) { wrapper.addEventListener('click', function() { if (links) { links.style.display = links.style.display === 'none' ? 'block' : 'none'; } }); } }); $(window).on('resize', scaleAnsiArt); })(); </script> {% else %} {# No ANSI file configured ? fall back to text menu #} {% include 'shells/bbs-menu/main-menu-text.twig' %} {% endif %}