Page 1 of 1

Browser Zoom Issues ..... workaround

Posted: Fri Aug 08, 2025 7:01 pm
by makeshyft
Hello All,

The browser got a big boost but it still has several bugs associated with zoom functions.

I've worked out a workaround for these issues an want to share them in case someone else comes across this and needs to gain control of the zoom.

The following code does these things:

1. intercepts ctrl mousewheel zoom gestures and blocks keyboard hotkeys
2. shows a panel; with a zoom slider
3. the ctrl+mousewheel is used to drive the slider
4. hides after 1 second

Code: Select all

on BrowserBro_InterceptZoomAndPanel pBrowser
   // BLOCK CTRL/CMD+WHEEL + KEYBOARD ZOOM; SHOW PANEL; WHEEL DRIVES SLIDER; AUTO-HIDE AFTER 1s
   local tScript, tError

   put "(function(){" into tScript
   put lf & "  var d = document;" after tScript
   put lf & "  var hideTimer = null;" after tScript

   // SHOW PANEL & RESET AUTO-HIDE TIMER
   put lf & "  function showPanelWithAutoHide() {" after tScript
   put lf & "    var refs = ensurePanel();" after tScript
   put lf & "    refs.panel.style.display = 'flex';" after tScript
   put lf & "    if (hideTimer) clearTimeout(hideTimer);" after tScript
   put lf & "    hideTimer = setTimeout(function(){ refs.panel.style.display = 'none'; }, 1000);" after tScript
   put lf & "    return refs;" after tScript
   put lf & "  }" after tScript

   // ENSURE PANEL EXISTS; RETURN {panel, slider}
   put lf & "  function ensurePanel() {" after tScript
   put lf & "    var panel = d.getElementById('bbZoomPanel');" after tScript
   put lf & "    var currentZoom = parseFloat(d.body.style.zoom || 1) || 1;" after tScript
   put lf & "    if (!panel) {" after tScript
   put lf & "      panel = d.createElement('div');" after tScript
   put lf & "      panel.id = 'bbZoomPanel';" after tScript
   put lf & "      panel.style.position = 'fixed';" after tScript
   put lf & "      panel.style.top = '10px';" after tScript
   put lf & "      panel.style.left = '5vw';" after tScript
   put lf & "      panel.style.width = '90vw';" after tScript
   put lf & "      panel.style.padding = '10px 14px';" after tScript
   put lf & "      panel.style.backgroundColor = 'rgba(0,0,0,0.5)';" after tScript
   put lf & "      panel.style.color = '#fff';" after tScript
   put lf & "      panel.style.borderRadius = '10px';" after tScript
   put lf & "      panel.style.fontFamily = 'system-ui, -apple-system, Segoe UI, Roboto, sans-serif';" after tScript
   put lf & "      panel.style.display = 'flex';" after tScript
   put lf & "      panel.style.alignItems = 'center';" after tScript
   put lf & "      panel.style.gap = '10px';" after tScript
   put lf & "      panel.style.boxSizing = 'border-box';" after tScript
   put lf & "      panel.style.zIndex = '2147483647';" after tScript
   put lf & "      panel.style.backdropFilter = 'blur(2px)';" after tScript
   put lf & "      panel.style.pointerEvents = 'auto';" after tScript

   put lf & "      var label = d.createElement('span');" after tScript
   put lf & "      label.id = 'bbZoomLabel';" after tScript
   put lf & "      label.textContent = 'Zoom:';" after tScript
   put lf & "      label.style.whiteSpace = 'nowrap';" after tScript
   put lf & "      label.style.fontWeight = '600';" after tScript

   put lf & "      var slider = d.createElement('input');" after tScript
   put lf & "      slider.id = 'bbZoomSlider';" after tScript
   put lf & "      slider.type = 'range';" after tScript
   put lf & "      slider.min = 0.1;" after tScript
   put lf & "      slider.max = 5.0;" after tScript
   put lf & "      slider.step = 0.1;" after tScript
   put lf & "      slider.value = currentZoom;" after tScript
   put lf & "      slider.style.flex = '1 1 auto';" after tScript
   put lf & "      slider.style.width = '100%';" after tScript

   put lf & "      var pct = d.createElement('span');" after tScript
   put lf & "      pct.id = 'bbZoomPct';" after tScript
   put lf & "      pct.textContent = Math.round(currentZoom * 100) + '%';" after tScript
   put lf & "      pct.style.whiteSpace = 'nowrap';" after tScript
   put lf & "      pct.style.minWidth = '48px';" after tScript
   put lf & "      pct.style.textAlign = 'right';" after tScript

   put lf & "      var eat = function(e){ e.stopPropagation(); };" after tScript
   put lf & "      ['mousedown','mouseup','click','dblclick','touchstart','touchmove','touchend','pointerdown','pointerup'].forEach(function(ev){" after tScript
   put lf & "        panel.addEventListener(ev, eat, true);" after tScript
   put lf & "      });" after tScript

   put lf & "      slider.oninput = function() {" after tScript
   put lf & "        var v = parseFloat(this.value) || 1;" after tScript
   put lf & "        d.body.style.zoom = v;" after tScript
   put lf & "        panel.style.zoom = (1 / v);" after tScript
   put lf & "        pct.textContent = Math.round(v * 100) + '%';" after tScript
   put lf & "      };" after tScript

   put lf & "      panel.appendChild(label);" after tScript
   put lf & "      panel.appendChild(slider);" after tScript
   put lf & "      panel.appendChild(pct);" after tScript
   put lf & "      d.body.appendChild(panel);" after tScript
   put lf & "    }" after tScript

   put lf & "    panel.style.zoom = (1 / (parseFloat(d.body.style.zoom || 1) || 1));" after tScript
   put lf & "    var s = d.getElementById('bbZoomSlider'); if (s) { s.dispatchEvent(new Event('input')); }" after tScript
   put lf & "    return { panel: panel, slider: d.getElementById('bbZoomSlider') };" after tScript
   put lf & "  }" after tScript

   put lf & "  function adjustZoomBy(steps) {" after tScript
   put lf & "    var refs = showPanelWithAutoHide();" after tScript
   put lf & "    var s = refs.slider;" after tScript
   put lf & "    if (!s) return;" after tScript
   put lf & "    var min = parseFloat(s.min)||0.1, max = parseFloat(s.max)||5.0, step = parseFloat(s.step)||0.1;" after tScript
   put lf & "    var v = parseFloat(s.value)||1;" after tScript
   put lf & "    v = v + steps*step;" after tScript
   put lf & "    if (v < min) v = min; if (v > max) v = max;" after tScript
   put lf & "    s.value = (Math.round(v/step)*step).toFixed(2);" after tScript
   put lf & "    s.dispatchEvent(new Event('input'));" after tScript
   put lf & "  }" after tScript

   put lf & "  d.addEventListener('wheel', function(e) {" after tScript
   put lf & "    if (e.ctrlKey || e.metaKey) {" after tScript
   put lf & "      e.preventDefault(); e.stopPropagation();" after tScript
   put lf & "      adjustZoomBy((e.deltaY > 0) ? -1 : 1);" after tScript
   put lf & "    }" after tScript
   put lf & "  }, { passive:false, capture:true });" after tScript

   put lf & "  d.addEventListener('wheel', function(e) {" after tScript
   put lf & "    var p = e.target && e.target.closest && e.target.closest('#bbZoomPanel');" after tScript
   put lf & "    if (p) {" after tScript
   put lf & "      e.preventDefault(); e.stopPropagation();" after tScript
   put lf & "      adjustZoomBy((e.deltaY > 0) ? -1 : 1);" after tScript
   put lf & "    }" after tScript
   put lf & "  }, { passive:false, capture:true });" after tScript

   put lf & "  d.addEventListener('keydown', function(e){" after tScript
   put lf & "    if (!(e.ctrlKey || e.metaKey)) return;" after tScript
   put lf & "    if (e.key === '+' || e.key === '=') { e.preventDefault(); e.stopPropagation(); adjustZoomBy(1); }" after tScript
   put lf & "    else if (e.key === '-' || e.key === '_') { e.preventDefault(); e.stopPropagation(); adjustZoomBy(-1); }" after tScript
   put lf & "    else if (e.key === '0') { e.preventDefault(); e.stopPropagation(); var refs = showPanelWithAutoHide(); if (refs.slider){ refs.slider.value = 1; refs.slider.dispatchEvent(new Event('input')); } }" after tScript
   put lf & "  }, true);" after tScript

   put lf & "})();" after tScript

   try
      if pBrowser = empty then
         do wrapInTry(tScript) in widget "JS Engine" of stack "AppStarterStack"
      else
         do wrapInTry(tScript) in widget ("Instance " & pBrowser) of group "Browsers" of this card of stack "AppStarterStack"
      end if
   catch tError
      put "JavaScript Error: " & tError
   end try
end BrowserBro_InterceptZoomAndPanel