-
Notifications
You must be signed in to change notification settings - Fork 0
Add click-to-copy for URL snippets in profile overview with i18n and keyboard accessibility #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
763f660
d3f73ce
25bc727
b076aed
014c3a9
18a1459
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| /** | ||
| * URL Generator - Backend JavaScript | ||
| * Adds click-to-copy functionality for URL call snippets | ||
| */ | ||
|
|
||
| (function($) { | ||
| 'use strict'; | ||
|
|
||
| $(document).ready(function() { | ||
| // Add click-to-copy functionality to code elements with data-copy-target attribute | ||
| $('.url-code-copy').on('click', function(e) { | ||
| e.preventDefault(); | ||
|
|
||
| var $this = $(this); | ||
| var targetId = $this.data('copy-target'); | ||
| var $textarea = $('#' + targetId); | ||
|
|
||
| if ($textarea.length === 0) { | ||
| console.error('Copy target textarea not found:', targetId); | ||
| return; | ||
| } | ||
|
|
||
| var textToCopy = $textarea.val(); | ||
|
|
||
| // Use the Clipboard API if available, fallback to older method | ||
| if (navigator.clipboard && window.isSecureContext) { | ||
| navigator.clipboard.writeText(textToCopy).then(function() { | ||
| showCopyFeedback($this); | ||
| }).catch(function(err) { | ||
| fallbackCopyToClipboard($textarea, $this); | ||
| }); | ||
| } else { | ||
| fallbackCopyToClipboard($textarea, $this); | ||
| } | ||
| }); | ||
|
|
||
| // Add keyboard accessibility (Enter or Space to trigger copy) | ||
| $('.url-code-copy').on('keydown', function(e) { | ||
| // Enter or Space key | ||
| if (e.key === 'Enter' || e.key === ' ') { | ||
| e.preventDefault(); | ||
| $(this).trigger('click'); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| /** | ||
| * Fallback copy method for older browsers or non-HTTPS contexts | ||
| */ | ||
| function fallbackCopyToClipboard($textarea, $element) { | ||
| $textarea[0].select(); | ||
|
||
|
|
||
| try { | ||
| document.execCommand('copy'); | ||
| showCopyFeedback($element); | ||
| } catch (err) { | ||
| console.error('Failed to copy text: ', err); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Show visual feedback when text is copied | ||
| */ | ||
| function showCopyFeedback($element) { | ||
| var $icon = $element.find('.rex-icon'); | ||
|
|
||
| // Change icon to checkmark temporarily | ||
| if ($icon.length) { | ||
| $icon.removeClass('fa-copy').addClass('fa-check'); | ||
| } | ||
|
|
||
| // Add success class | ||
| $element.addClass('url-copied'); | ||
|
|
||
| // Reset after 2 seconds | ||
| setTimeout(function() { | ||
| if ($icon.length) { | ||
| $icon.removeClass('fa-check').addClass('fa-copy'); | ||
| } | ||
| $element.removeClass('url-copied'); | ||
| }, 2000); | ||
| } | ||
|
|
||
| })(jQuery); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,9 +96,11 @@ class="btn btn-primary btn-xs pull-right" | |
| ?> | ||
| <p class="help-block rex-note" style="font-size: 0.8em;"> | ||
| Aufruf via | ||
| <code>rex_getUrl('', '', ['<?= htmlspecialchars($profile['namespace'] ?? '') ?>' => {id}])</code> | ||
| <code class="url-code-copy" data-copy-target="url-copy-<?= $profile['id'] ?>-1" title="<?= rex_i18n::msg('url_click_to_copy') ?>" tabindex="0"><i class="rex-icon fa-copy"></i> rex_getUrl('', '', ['<?= rex_escape($profile['namespace'] ?? '') ?>' => {id}])</code> | ||
| <textarea id="url-copy-<?= $profile['id'] ?>-1" style="position: absolute; left: -9999px;" aria-hidden="true" tabindex="-1">rex_getUrl('', '', ['<?= rex_escape($profile['namespace'] ?? '') ?>' => {id}])</textarea> | ||
| oder via Artikel | ||
| <code>rex_article::get(<?= $article->getId() ?>)->getUrl(['<?= htmlspecialchars($profile['namespace'] ?? '') ?>' => {id}])</code><br> | ||
| <code class="url-code-copy" data-copy-target="url-copy-<?= $profile['id'] ?>-2" title="<?= rex_i18n::msg('url_click_to_copy') ?>" tabindex="0"><i class="rex-icon fa-copy"></i> rex_article::get(<?= $article->getId() ?>)->getUrl(['<?= rex_escape($profile['namespace'] ?? '') ?>' => {id}])</code><br> | ||
|
Comment on lines
+99
to
+102
|
||
| <textarea id="url-copy-<?= $profile['id'] ?>-2" style="position: absolute; left: -9999px;" aria-hidden="true" tabindex="-1">rex_article::get(<?= $article->getId() ?>)->getUrl(['<?= rex_escape($profile['namespace'] ?? '') ?>' => {id}])</textarea> | ||
|
Comment on lines
+99
to
+103
|
||
|
|
||
|
|
||
| </p> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code constructs a jQuery selector by directly concatenating the
targetIdfrom the data attribute ($('#' + targetId)). If the ID contains special characters (like dots, colons, brackets), the selector could fail or behave unexpectedly.Consider using
document.getElementById(targetId)wrapped in jQuery ($(document.getElementById(targetId))) instead, which is safer and doesn't require escaping special characters in IDs.