Browse Source

Add a "Copied" tooltip to the copy-to-clipboard button

This is not the ideal version, since the height is too low for the tooltip
used for the drop-down menus. Probably has something to do with the
container or something. But at least something is there now, even if
not the most beautiful.
pull/1438/head
Florian Zschocke 1 year ago
parent
commit
be7d1b1beb

+ 5
- 0
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java View File

@@ -171,6 +171,11 @@ public abstract class RepositoryPage extends RootPage {
add(searchForm);
searchForm.setTranslatedAttributes();
// load clipboard library to copy repository URL
addBottomScript("../../clipboard/clipboard.min.js");
// instantiate clipboard
addBottomScript("../../clipboard/gitblit-ctcbtn.js");
// set stateless page preference
setStatelessHint(true);
}

+ 0
- 7
src/main/java/com/gitblit/wicket/pages/SummaryPage.html View File

@@ -62,13 +62,6 @@
</wicket:fragment>
<!-- load clipboard library to copy repository URL -->
<script type="text/javascript" src="clipboard/clipboard.min.js"></script>
<!-- instantiate clipboard -->
<script>
var clipboard = new ClipboardJS('.ctcbtn');
</script>
</wicket:extend>
</body>
</html>

+ 6
- 4
src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html View File

@@ -12,12 +12,14 @@
<wicket:fragment wicket:id="repositoryUrlFragment">
<div class="btn-toolbar" style="margin: 0px;">
<div class="btn-group repositoryUrlContainer">
<div class="btn-group repositoryUrlContainer tooltipped tooltipped-w">
<img style="vertical-align: middle;padding: 0px 0px 1px 3px;" wicket:id="accessRestrictionIcon"></img>
<span wicket:id="menu"></span>
<div class="repositoryUrl">
<span wicket:id="primaryUrl">[repository primary url]</span>
<span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>
<span class="tooltipped tooltipped-n">
<span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>
</span>
</div>
<span class="hidden-phone hidden-tablet repositoryUrlRightCap" wicket:id="primaryUrlPermission">[repository primary url permission]</span>
</div>
@@ -33,7 +35,7 @@
<wicket:fragment wicket:id="applicationMenusFragment">
<div class="btn-toolbar" style="margin: 4px 0px 0px 0px;">
<div class="btn-group" wicket:id="appMenus">
<div class="btn-group tooltipped tooltipped-w" wicket:id="appMenus">
<span wicket:id="appMenu"></span>
</div>
</div>
@@ -87,7 +89,7 @@
<!-- JavaScript automatic copy to clipboard -->
<wicket:fragment wicket:id="clippyPanel">
<img class="ctcbtn" data-clipboard-action="copy" wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard" />
<img class="ctcbtn" wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard" />
</wicket:fragment>
<wicket:fragment wicket:id="workingCopyFragment">

+ 72
- 0
src/main/resources/clipboard/gitblit-ctcbtn.js View File

@@ -0,0 +1,72 @@
// Instantiate the clipboarding
var clipboard = new ClipboardJS('.ctcbtn');

clipboard.on('success', function (e) {
showTooltip(e.trigger, 'Copied!');
});

clipboard.on('error', function (e) {
showTooltip(e.trigger, fallbackMessage(e.action));
});

// Attach events to buttons to clear tooltip again
var btns = document.querySelectorAll('.ctcbtn');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('mouseleave', clearTooltip);
btns[i].addEventListener('blur', clearTooltip);
}

// Show or hide tooltip by setting the tooltipped-active class
// on a parent that containes tooltipped. Since the copy button
// could be and image, or be hidden after clicking, the tooltipped
// emelent might be higher in the hierarchy.
var ttset
function showTooltip(elem, msg) {
let ttelem = findTooltipped(elem);
if (ttelem != null) {
ttelem.classList.add('tooltipped-active');
ttelem.setAttribute('data-tt-text', msg);
ttset=Date.now();
}
else {
console.warn("Could not find any tooltipped element for clipboard button.", elem);
}
}
function clearTooltip(e) {
let ttelem = findTooltipped(e.currentTarget);
if (ttelem != null) {
let now = Date.now();
if (now - ttset < 500) {
// Give the tooltip some time to display
setTimeout(function(){ttelem.classList.remove('tooltipped-active')}, 1000)
}
else {
ttelem.classList.remove('tooltipped-active');
// e.currentTarget.removeAttribute('data-tt-text');
}
}
else {
console.warn("Could not find any tooltipped element for clipboard button.", e.currentTarget);
}
}
function findTooltipped(elem) {
do {
if (elem.classList.contains('tooltipped')) return elem;
elem = elem.parentElement;
} while (elem != null);
return null;
}

// If the API is not supported, at least fall back to a message saying
// that now that the text is selected, Ctrl-C can be used.
// This is still a problem in the repo URL dropdown. When it is hidden, Ctrl-C doesn't work.
function fallbackMessage(action) {
var actionMsg = '';
if (/Mac/i.test(navigator.userAgent)) {
actionMsg = 'Press ⌘-C to copy';
}
else {
actionMsg = 'Press Ctrl-C to copy';
}
return actionMsg;
}

+ 171
- 1
src/main/resources/gitblit.css View File

@@ -2408,4 +2408,174 @@ table.filestore-status {
font-weight: 200;
font-size: 1em;
font-variant: normal;
}
}
/*
Copy-to-clipboard tooltip styling from Github's primer.css
https://primer.style/css/components/tooltips
Adjusted to not hover but fade-in/out on clipboard events.
*/
.tooltipped {
position:relative
}
.tooltipped:after {
position: absolute;
z-index: 1000000;
padding: 5px 8px;
font: normal normal 11px/1.5 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
color: #fff;
background: rgba(42, 42, 42, .8);
text-align: center;
text-decoration: none;
text-shadow: none;
text-transform: none;
letter-spacing: normal;
word-wrap: break-word;
white-space: pre;
pointer-events: none;
content: attr(data-tt-text);
border-radius: 3px;
-webkit-font-smoothing:subpixel-antialiased;
opacity: 0;
transition: 0.5s opacity;
}
.tooltipped:before {
position: absolute;
z-index: 1000001;
width: 0;
height: 0;
color: rgba(42, 42, 42, .8);
pointer-events: none;
content: "";
border:5px solid transparent;
opacity: 0;
transition: 0.5s opacity;
}
.tooltipped-active:before, .tooltipped-active:after {
opacity: 1;
text-decoration:none
}
.tooltipped-s:after, .tooltipped-se:after, .tooltipped-sw:after {
top: 100%;
right: 50%;
margin-top:5px
}
.tooltipped-s:before, .tooltipped-se:before, .tooltipped-sw:before {
top: auto;
right: 50%;
bottom: -5px;
margin-right: -5px;
border-bottom-color:rgba(42, 42, 42, .8)
}
.tooltipped-se:after {
right: auto;
left: 50%;
margin-left:-15px
}
.tooltipped-sw:after {
margin-right:-15px
}
.tooltipped-n:after, .tooltipped-ne:after, .tooltipped-nw:after {
right: 50%;
bottom: 100%;
margin-bottom:5px
}
.tooltipped-n:before, .tooltipped-ne:before, .tooltipped-nw:before {
top: -5px;
right: 50%;
bottom: auto;
margin-right: -5px;
border-top-color:rgba(42, 42, 42, .8)
}
.tooltipped-ne:after {
right: auto;
left: 50%;
margin-left:-15px
}
.tooltipped-nw:after {
margin-right:-15px
}
.tooltipped-s:after, .tooltipped-n:after {
-webkit-transform: translateX(50%);
-ms-transform: translateX(50%);
transform:translateX(50%)
}
.tooltipped-w:after {
right: 100%;
bottom: 50%;
margin-right: 5px;
-webkit-transform: translateY(50%);
-ms-transform: translateY(50%);
transform:translateY(50%)
}
.tooltipped-w:before {
top: 50%;
bottom: 50%;
left: -5px;
margin-top: -5px;
border-left-color:rgba(42, 42, 42, .8)
}
.tooltipped-e:after {
bottom: 50%;
left: 100%;
margin-left: 5px;
-webkit-transform: translateY(50%);
-ms-transform: translateY(50%);
transform:translateY(50%)
}
.tooltipped-e:before {
top: 50%;
right: -5px;
bottom: 50%;
margin-top: -5px;
border-right-color:rgba(42, 42, 42, .8)
}
.tooltipped-sticky:before, .tooltipped-sticky:after {
display:inline-block
}
.fullscreen-overlay-enabled.dark-theme .tooltipped:after {
color: #000;
background:rgba(200, 200, 200, .8)
}
.fullscreen-overlay-enabled.dark-theme .tooltipped .tooltipped-s:before, .fullscreen-overlay-enabled.dark-theme .tooltipped .tooltipped-se:before, .fullscreen-overlay-enabled.dark-theme .tooltipped .tooltipped-sw:before {
border-bottom-color:rgba(200, 200, 200, .8)
}
.fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-n:before, .fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-ne:before, .fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-nw:before {
border-top-color:rgba(200, 200, 200, .8)
}
.fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-e:before {
border-right-color:rgba(200, 200, 200, .8)
}
.fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-w:before {
border-left-color:rgba(200, 200, 200, .8)
}

Loading…
Cancel
Save