[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX][ENH] Teleprompter: Improve Teleprompter controls and fullscreen UX

"Bruno Kambere \(@kambereBr\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <6a22ae39180fb_3819460006c@gitlab-sidekiq-low-urgency-cpu-bound-v2-679d75d87c-pvwsn.mail>

Bruno Kambere pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
76b7692e by UshindiG at 2026-06-05T13:49:09+03:00
[FIX][ENH] Teleprompter: Improve Teleprompter controls and fullscreen UX
---
* [FIX][ENH] Teleprompter: Improve Teleprompter controls and fullscreen UX

See merge request tikiwiki/tiki!10405

- - - - -


3 changed files:

- lib/wiki-plugins/css/teleprompter.css
- lib/wiki-plugins/js/teleprompter.js
- lib/wiki-plugins/wikiplugin_teleprompter.php


Changes:

=====================================
lib/wiki-plugins/css/teleprompter.css
=====================================
@@ -10,6 +10,18 @@
   margin-bottom: 20px;
 }
 
+.teleprompter-container:fullscreen {
+  width: 100% !important;
+  height: 100% !important;
+  background: #000;
+}
+
+.teleprompter-container:-webkit-full-screen {
+  width: 100% !important;
+  height: 100% !important;
+  background: #000;
+}
+
 .teleprompter-container:focus-visible {
   outline: 2px solid rgba(255, 255, 255, 0.7);
   outline-offset: 2px;
@@ -137,11 +149,25 @@
   bottom: 10px;
   z-index: 3;
   display: flex;
-  gap: 8px;
+  flex-wrap: wrap;
+  gap: 6px;
+  max-width: calc(100% - 120px);
+  padding: 4px;
+  border-radius: 6px;
+  background: rgba(0, 0, 0, 0.35);
+  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
+  opacity: 0;
+  pointer-events: none;
+  transition: opacity 0.16s ease-in-out;
 }
 
 .teleprompter-controls-hidden {
-  display: none;
+  display: none !important;
+}
+
+.teleprompter-control-group {
+  display: flex;
+  gap: 4px;
 }
 
 .teleprompter-btn {
@@ -151,15 +177,23 @@
   background: rgba(0, 0, 0, 0.55);
   color: #fff;
   font-size: 12px;
+  font-weight: 600;
   line-height: 1;
-  padding: 0.4rem 0.6rem;
+  padding: 0.35rem 0.5rem;
   cursor: pointer;
+  min-width: 32px;
+  min-height: 30px;
 }
 
 .teleprompter-btn:hover {
   background: rgba(0, 0, 0, 0.7);
 }
 
+.teleprompter-btn-active {
+  background: rgba(255, 255, 255, 0.22);
+  border-color: rgba(255, 255, 255, 0.75);
+}
+
 .teleprompter-btn:focus-visible {
   outline: 2px solid rgba(255, 255, 255, 0.7);
   outline-offset: 2px;
@@ -178,8 +212,28 @@
   font-family: monospace;
   line-height: 1;
   font-variant-numeric: tabular-nums;
+  opacity: 0;
+  pointer-events: none;
+  transition: opacity 0.16s ease-in-out;
+}
+
+.teleprompter-container:hover .teleprompter-controls,
+.teleprompter-container:focus-within .teleprompter-controls,
+.teleprompter-container.teleprompter-controls-active .teleprompter-controls,
+.teleprompter-container:hover .teleprompter-timer,
+.teleprompter-container:focus-within .teleprompter-timer,
+.teleprompter-container.teleprompter-controls-active .teleprompter-timer {
+  opacity: 1;
+  pointer-events: auto;
 }
 
 .teleprompter-timer-hidden {
-  display: none;
+  display: none !important;
+}
+
+@media (max-width: 576px) {
+  .teleprompter-controls {
+    right: 12px;
+    max-width: calc(100% - 24px);
+  }
 }


=====================================
lib/wiki-plugins/js/teleprompter.js
=====================================
@@ -53,8 +53,10 @@
             pausedByUser: false,
             reachedEnd: false,
             resizeDebounceId: null,
+            controlsVisibilityTimer: null,
             speed: clamp(Math.abs(toNumber(opts.speed, 35)), settings.minSpeed, settings.maxSpeed)
         };
+        var initialSpeed = state.speed;
         if (settings.reverseScroll) {
             state.speed = -state.speed;
         }
@@ -68,6 +70,9 @@
         var $controls = $container.find(".teleprompter-controls");
         var $toggleControl = $controls.find(".teleprompter-btn-toggle");
         var $restartControl = $controls.find(".teleprompter-btn-restart");
+        var $speedControls = $controls.find("[data-tp-speed]");
+        var $fontControls = $controls.find("[data-tp-font]");
+        var $fullscreenControl = $controls.find("[data-tp-fullscreen]");
         var $progress = $container.find(".teleprompter-progress");
         var $progressThumb = $progress.find(".teleprompter-progress-thumb");
 
@@ -75,6 +80,21 @@
             return settings.reverseScroll && state.maxOffset > 0 ? state.maxOffset : 0;
         };
 
+        var revealControls = function () {
+            if (!settings.showControls) {
+                return;
+            }
+
+            $container.addClass("teleprompter-controls-active");
+            if (state.controlsVisibilityTimer !== null) {
+                window.clearTimeout(state.controlsVisibilityTimer);
+            }
+            state.controlsVisibilityTimer = window.setTimeout(function () {
+                state.controlsVisibilityTimer = null;
+                $container.removeClass("teleprompter-controls-active");
+            }, 3000);
+        };
+
         var updateToggleControl = function () {
             if (!$toggleControl.length) {
                 return;
@@ -234,6 +254,7 @@
 
         var restartFromBeginning = function () {
             refreshLayout();
+            state.speed = settings.reverseScroll ? -initialSpeed : initialSpeed;
             state.offset = getStartOffset();
             state.elapsedMs = 0;
             state.lastTs = null;
@@ -296,6 +317,65 @@
             }
         };
 
+        var fullscreenElement = function () {
+            return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
+        };
+
+        var enterFullscreen = function () {
+            var element = $container.get(0);
+            if (!element) {
+                return false;
+            }
+
+            var requestFullscreen = element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullScreen || element.msRequestFullscreen;
+            if (typeof requestFullscreen !== "function") {
+                return false;
+            }
+
+            requestFullscreen.call(element);
+            return true;
+        };
+
+        var exitFullscreen = function () {
+            var exit = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
+            if (typeof exit === "function") {
+                exit.call(document);
+            }
+        };
+
+        var updateFullscreenControl = function () {
+            if (!$fullscreenControl.length) {
+                return;
+            }
+
+            var isFullscreen = fullscreenElement() === $container.get(0);
+            var label = isFullscreen ? $fullscreenControl.data("tpExitFullscreenLabel") : $fullscreenControl.data("tpFullscreenLabel");
+            $fullscreenControl
+                .empty()
+                .append($("<span>", {
+                    "aria-hidden": "true",
+                    "class": "fas " + (isFullscreen ? "fa-compress" : "fa-expand")
+                }))
+                .append($("<span>", {
+                    "class": "visually-hidden",
+                    text: label
+                }))
+                .attr({
+                    "aria-label": label,
+                    "aria-pressed": isFullscreen ? "true" : "false",
+                    title: label
+                })
+                .toggleClass("teleprompter-btn-active", isFullscreen);
+        };
+
+        var toggleFullscreen = function () {
+            if (fullscreenElement() === $container.get(0)) {
+                exitFullscreen();
+            } else {
+                enterFullscreen();
+            }
+        };
+
         var applyFontScaleStep = function (direction, stepCount) {
             stepCount = Math.max(1, stepCount || 1);
             state.fontScale = clamp(state.fontScale + direction * settings.fontScaleStep * stepCount, settings.minFontScale, settings.maxFontScale);
@@ -359,7 +439,11 @@
         if (!settings.showControls && $controls.length) {
             $controls.addClass("teleprompter-controls-hidden");
         }
+        if (!$container.get(0).requestFullscreen && !$container.get(0).webkitRequestFullscreen && !$container.get(0).mozRequestFullScreen && !$container.get(0).msRequestFullscreen) {
+            $fullscreenControl.hide();
+        }
         updateToggleControl();
+        updateFullscreenControl();
 
         $content.find("img").off(eventNamespace).on("load" + eventNamespace, function () {
             refreshLayout();
@@ -395,6 +479,30 @@
             $container.trigger("focus");
         });
 
+        $speedControls.off(eventNamespace).on("click" + eventNamespace, function (e) {
+            e.preventDefault();
+            applySpeedStep(toNumber($(this).data("tpSpeed"), 1), 1);
+            $container.trigger("focus");
+        });
+
+        $fontControls.off(eventNamespace).on("click" + eventNamespace, function (e) {
+            e.preventDefault();
+            applyFontScaleStep(toNumber($(this).data("tpFont"), 1), 1);
+            $container.trigger("focus");
+        });
+
+        $fullscreenControl.off(eventNamespace).on("click" + eventNamespace, function (e) {
+            e.preventDefault();
+            toggleFullscreen();
+            $container.trigger("focus");
+        });
+
+        $(document).off("fullscreenchange" + eventNamespace + " webkitfullscreenchange" + eventNamespace + " mozfullscreenchange" + eventNamespace + " MSFullscreenChange" + eventNamespace)
+            .on("fullscreenchange" + eventNamespace + " webkitfullscreenchange" + eventNamespace + " mozfullscreenchange" + eventNamespace + " MSFullscreenChange" + eventNamespace, function () {
+                updateFullscreenControl();
+                refreshLayout();
+            });
+
         $container.off(eventNamespace).on("keydown" + eventNamespace, function (e) {
             var target = e.target;
             var tagName = target && target.tagName ? target.tagName.toLowerCase() : "";
@@ -402,6 +510,8 @@
                 return;
             }
 
+            revealControls();
+
             var key = e.key || "";
             var lowerKey = key.toLowerCase();
 
@@ -418,6 +528,12 @@
                 return;
             }
 
+            if (lowerKey === "f") {
+                toggleFullscreen();
+                e.preventDefault();
+                return;
+            }
+
             if (key === "ArrowDown" || lowerKey === "s") {
                 applySpeedStep(1, 1);
                 e.preventDefault();
@@ -450,6 +566,8 @@
             var stepCount = Math.max(1, Math.min(5, Math.round(Math.abs(originalEvent.deltaY) / 100)));
             applySpeedStep(direction, stepCount);
             e.preventDefault();
+        }).on("focus" + eventNamespace + " mousemove" + eventNamespace + " touchstart" + eventNamespace, function () {
+            revealControls();
         });
     };
 })(jQuery);


=====================================
lib/wiki-plugins/wikiplugin_teleprompter.php
=====================================
@@ -338,6 +338,12 @@ function wikiplugin_teleprompter($data, $params)
     $teleprompterControlsLabel = htmlspecialchars(tr('Teleprompter controls'), ENT_QUOTES);
     $pauseButtonLabel = htmlspecialchars(tr('Pause'), ENT_QUOTES);
     $restartButtonLabel = htmlspecialchars(tr('Restart'), ENT_QUOTES);
+    $slowerButtonLabel = htmlspecialchars(tr('Slower'), ENT_QUOTES);
+    $fasterButtonLabel = htmlspecialchars(tr('Faster'), ENT_QUOTES);
+    $smallerTextButtonLabel = htmlspecialchars(tr('Smaller text'), ENT_QUOTES);
+    $largerTextButtonLabel = htmlspecialchars(tr('Larger text'), ENT_QUOTES);
+    $fullscreenButtonLabel = htmlspecialchars(tr('Fullscreen'), ENT_QUOTES);
+    $exitFullscreenButtonLabel = htmlspecialchars(tr('Exit fullscreen'), ENT_QUOTES);
 
     return '<div id="' . $containerId . '" class="teleprompter-container' . $mirrorClass . $focusClass . '" role="region" aria-label="' . $teleprompterRegionLabel . '" tabindex="0">' .
         '<div id="' . $trackId . '" class="teleprompter-track">' .
@@ -346,8 +352,19 @@ function wikiplugin_teleprompter($data, $params)
         '<div class="teleprompter-focus-overlay" aria-hidden="true"><div class="tp-focus-mask tp-focus-mask-top"></div><div class="tp-focus-mask tp-focus-mask-bottom"></div><div class="tp-focus-guide"></div></div>' .
         '<div class="teleprompter-progress" aria-hidden="true"><div class="teleprompter-progress-thumb"></div></div>' .
         '<div class="teleprompter-controls' . $controlsClass . '" aria-label="' . $teleprompterControlsLabel . '">' .
+        '<div class="teleprompter-control-group">' .
         '<button type="button" class="teleprompter-btn teleprompter-btn-toggle" data-tp-toggle="1" aria-pressed="false">' . $pauseButtonLabel . '</button>' .
         '<button type="button" class="teleprompter-btn teleprompter-btn-restart" data-tp-restart="1">' . $restartButtonLabel . '</button>' .
+        '<button type="button" class="teleprompter-btn teleprompter-btn-fullscreen" data-tp-fullscreen="1" title="' . $fullscreenButtonLabel . '" aria-label="' . $fullscreenButtonLabel . '" data-tp-fullscreen-label="' . $fullscreenButtonLabel . '" data-tp-exit-fullscreen-label="' . $exitFullscreenButtonLabel . '" aria-pressed="false"><span class="fas fa-expand" aria-hidden="true"></span><span class="visually-hidden">' . $fullscreenButtonLabel . '</span></button>' .
+        '</div>' .
+        '<div class="teleprompter-control-group">' .
+        '<button type="button" class="teleprompter-btn" data-tp-speed="-1" title="' . $slowerButtonLabel . '" aria-label="' . $slowerButtonLabel . '"><span class="fas fa-backward" aria-hidden="true"></span><span class="visually-hidden">' . $slowerButtonLabel . '</span></button>' .
+        '<button type="button" class="teleprompter-btn" data-tp-speed="1" title="' . $fasterButtonLabel . '" aria-label="' . $fasterButtonLabel . '"><span class="fas fa-forward" aria-hidden="true"></span><span class="visually-hidden">' . $fasterButtonLabel . '</span></button>' .
+        '</div>' .
+        '<div class="teleprompter-control-group">' .
+        '<button type="button" class="teleprompter-btn" data-tp-font="-1" title="' . $smallerTextButtonLabel . '" aria-label="' . $smallerTextButtonLabel . '">A-</button>' .
+        '<button type="button" class="teleprompter-btn" data-tp-font="1" title="' . $largerTextButtonLabel . '" aria-label="' . $largerTextButtonLabel . '">A+</button>' .
+        '</div>' .
         '</div>' .
         '<div id="' . $timerId . '" class="teleprompter-timer' . $timerClass . '" aria-live="polite" aria-atomic="true">00:00</div>' .
         '</div>';



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/76b7692ec860ee3b6f47198558588dd90e650ee7

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/76b7692ec860ee3b6f47198558588dd90e650ee7
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.