Parcourir la source

prototype keyboard trap toggle

- needs updating all language files
- replicate changes to all templates
El RIDO il y a 1 an
Parent
commit
544c4d2f5f
6 fichiers modifiés avec 41 ajouts et 13 suppressions
  1. 1 0
      CHANGELOG.md
  2. 4 2
      i18n/en.json
  3. 1 1
      js/dark-mode-switch.js
  4. 24 5
      js/privatebin.js
  5. 1 1
      lib/Configuration.php
  6. 10 4
      tpl/bootstrap5.php

+ 1 - 0
CHANGELOG.md

@@ -1,6 +1,7 @@
 # PrivateBin version history
 # PrivateBin version history
 
 
 ## 1.7.6 (not yet released)
 ## 1.7.6 (not yet released)
+* CHANGED: Allow toggling tab-key-support using `[Ctrl]+[m]` or `[Esc]` in textarea for keyboard navigation (#1386)
 
 
 ## 1.7.5 (2024-11-16)
 ## 1.7.5 (2024-11-16)
 * ADDED: Allow non persistent SQL connections, if configured (#1394)
 * ADDED: Allow non persistent SQL connections, if configured (#1394)

+ 4 - 2
i18n/en.json

@@ -151,7 +151,7 @@
     "server error or not responding": "server error or not responding",
     "server error or not responding": "server error or not responding",
     "Could not post comment: %s": "Could not post comment: %s",
     "Could not post comment: %s": "Could not post comment: %s",
     "Sending paste…": "Sending paste…",
     "Sending paste…": "Sending paste…",
-    "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>",
+    "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>",
     "Delete data": "Delete data",
     "Delete data": "Delete data",
     "Could not create paste: %s": "Could not create paste: %s",
     "Could not create paste: %s": "Could not create paste: %s",
     "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
     "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
@@ -220,5 +220,7 @@
     "Dark Mode": "Dark Mode",
     "Dark Mode": "Dark Mode",
     "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.",
     "Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.",
     "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.",
     "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.",
-    "Start over": "Start over"
+    "Start over": "Start over",
+    "Paste text": "Paste text",
+    "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)"
 }
 }

+ 1 - 1
js/dark-mode-switch.js

@@ -68,7 +68,7 @@
     } else {
     } else {
       delStoredPrettifyTheme()
       delStoredPrettifyTheme()
     }
     }
-    const toggle = document.querySelector('#bd-theme')
+    const toggle = document.getElementById('bd-theme')
     const theme = getStoredPreferredTheme()
     const theme = getStoredPreferredTheme()
     setTheme(theme)
     setTheme(theme)
     toggle.checked = (theme === 'dark')
     toggle.checked = (theme === 'dark')

+ 24 - 5
js/privatebin.js

@@ -2092,7 +2092,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         {
         {
             I18n._(
             I18n._(
                 $('#pastelink'),
                 $('#pastelink'),
-                'Your paste is <a id="pasteurl" href="%s">%s</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>',
+                'Your paste is <a id="pasteurl" href="%s">%s</a> <span id="copyhint">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>',
                 url, url
                 url, url
             );
             );
             // save newly created element
             // save newly created element
@@ -2394,7 +2394,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             $messagePreview,
             $messagePreview,
             $messagePreviewParent,
             $messagePreviewParent,
             $message,
             $message,
-            isPreview = false;
+            isPreview = false,
+            isTabSupported = true;
 
 
         /**
         /**
          * support input of tab character
          * support input of tab character
@@ -2406,9 +2407,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
          */
         function supportTabs(event)
         function supportTabs(event)
         {
         {
-            const keyCode = event.keyCode || event.which;
+            // support disabling tab support using [Esc] and [Ctrl]+[m]
+            if (event.key === 'Escape' || (event.ctrlKey && event.key === 'm')) {
+                toggleTabSupport();
+                document.getElementById('message-tab').checked = isTabSupported;
+                event.preventDefault();
+            }
             // tab was pressed
             // tab was pressed
-            if (keyCode === 9) {
+            else if (isTabSupported && event.key === 'Tab') {
                 // get caret position & selection
                 // get caret position & selection
                 const val   = this.value,
                 const val   = this.value,
                       start = this.selectionStart,
                       start = this.selectionStart,
@@ -2422,6 +2428,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             }
             }
         }
         }
 
 
+        /**
+         * toggle tab support in message textarea
+         *
+         * @name   Editor.toggleTabSupport
+         * @private
+         * @function
+         */
+        function toggleTabSupport()
+        {
+            isTabSupported = !isTabSupported;
+        }
+
         /**
         /**
          * view the Editor tab
          * view the Editor tab
          *
          *
@@ -2599,6 +2617,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
 
             // bind events
             // bind events
             $message.keydown(supportTabs);
             $message.keydown(supportTabs);
+            $('#message-tab').change(toggleTabSupport);
 
 
             // bind click events to tab switchers (a), and save parents (li)
             // bind click events to tab switchers (a), and save parents (li)
             $messageEdit = $('#messageedit').click(viewEditor);
             $messageEdit = $('#messageedit').click(viewEditor);
@@ -3768,7 +3787,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
 
         /**
         /**
          * Clear the password input in the top navigation
          * Clear the password input in the top navigation
-         * 
+         *
          * @name TopNav.clearPasswordInput
          * @name TopNav.clearPasswordInput
          * @function
          * @function
          */
          */

+ 1 - 1
lib/Configuration.php

@@ -108,7 +108,7 @@ class Configuration
             'js/kjua-0.9.0.js'       => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
             'js/kjua-0.9.0.js'       => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
             'js/legacy.js'           => 'sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==',
             'js/legacy.js'           => 'sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
-            'js/privatebin.js'       => 'sha512-JUj/Sbl/bMHlIoIUT1U9e89JU33fDBxCxLSGxwwaeydBFXOBHyfdF7hwSIjgbPxb4d9CO7CSe4meouTIRMy8Vg==',
+            'js/privatebin.js'       => 'sha512-V0coVhQkhG/bSJcZAMOoR+9Ztak1hElXiOtcrR4zZYm4MwScgytYHPVeZa6ZVKf+Mxp5TtIvM+NcYixP33Yliw==',
             'js/purify-3.1.7.js'     => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==',
             'js/purify-3.1.7.js'     => 'sha512-LegvqULiMtOfboJZw9MpETN/b+xnLRXZI90gG7oIFHW+yAeHmKvRtEUbiMFx2WvUqQoL9XB3gwU+hWXUT0X+8A==',
             'js/rawinflate-0.3.js'   => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
             'js/rawinflate-0.3.js'   => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',

+ 10 - 4
tpl/bootstrap5.php

@@ -88,7 +88,7 @@ endif;
 						<form id="passwordform" role="form">
 						<form id="passwordform" role="form">
 							<div class="mb-3">
 							<div class="mb-3">
 								<label for="passworddecrypt"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#eye" /></svg> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
 								<label for="passworddecrypt"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#eye" /></svg> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
-								<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" required="required">
+								<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" required="required" />
 							</div>
 							</div>
 							<button type="submit" class="btn btn-success btn-block"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#power" /></svg> <?php echo I18n::_('Decrypt') ?></button>
 							<button type="submit" class="btn btn-success btn-block"><svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#power" /></svg> <?php echo I18n::_('Decrypt') ?></button>
 						</form>
 						</form>
@@ -249,7 +249,7 @@ if ($PASSWORD) :
 ?>
 ?>
 						<li class="nav-item">
 						<li class="nav-item">
 							<div id="password" class="navbar-form hidden">
 							<div id="password" class="navbar-form hidden">
-								<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="23" />
+								<input type="password" id="passwordinput" placeholder="<?php echo I18n::_('Password (recommended)'); ?>" aria-label="<?php echo I18n::_('Password (recommended)'); ?>" class="form-control" size="23" />
 							</div>
 							</div>
 						</li>
 						</li>
 <?php
 <?php
@@ -296,7 +296,7 @@ endif;
 					<ul class="navbar-nav gap-2">
 					<ul class="navbar-nav gap-2">
 						<li class="nav-item">
 						<li class="nav-item">
 							<div class="form-check form-switch navbar-text">
 							<div class="form-check form-switch navbar-text">
-								<input id="bd-theme" type="checkbox" class="form-check-input">
+								<input id="bd-theme" type="checkbox" class="form-check-input" />
 								<label for="bd-theme" class="form-check-label"><?php echo I18n::_('Dark Mode'); ?></label>
 								<label for="bd-theme" class="form-check-label"><?php echo I18n::_('Dark Mode'); ?></label>
 							</div>
 							</div>
 						</li>
 						</li>
@@ -439,7 +439,13 @@ endif;
 						<pre id="prettyprint" class="card-body col-md-12 prettyprint linenums:1"></pre>
 						<pre id="prettyprint" class="card-body col-md-12 prettyprint linenums:1"></pre>
 					</div>
 					</div>
 					<div id="plaintext" class="col-md-12 hidden"></div>
 					<div id="plaintext" class="col-md-12 hidden"></div>
-					<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
+					<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" aria-label="<?php echo I18n::_('Paste text'); ?>" class="form-control hidden"></textarea></p>
+					<p class="col-md-12" id="message-controls">
+						<input id="message-tab" type="checkbox" class="form-check-input" checked="checked" />
+						<label for="message-tab" class="form-check-label">
+							<?php echo I18n::_('Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)'); ?>
+						</label>
+					</p>
 				</article>
 				</article>
 			</section>
 			</section>
 			<section class="container-fluid">
 			<section class="container-fluid">