\r
<wicket:fragment wicket:id="repositoryUrlFragment">\r
<div class="btn-toolbar" style="margin: 0px;">\r
- <div class="btn-group repositoryUrlContainer">\r
+ <div class="btn-group repositoryUrlContainer tooltipped tooltipped-w">\r
<img style="vertical-align: middle;padding: 0px 0px 1px 3px;" wicket:id="accessRestrictionIcon"></img>\r
<span wicket:id="menu"></span>\r
<div class="repositoryUrl">\r
<span wicket:id="primaryUrl">[repository primary url]</span>\r
- <span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>\r
+ <span class="tooltipped tooltipped-n">\r
+ <span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>\r
+ </span>\r
</div>\r
<span class="hidden-phone hidden-tablet repositoryUrlRightCap" wicket:id="primaryUrlPermission">[repository primary url permission]</span>\r
</div>\r
\r
<wicket:fragment wicket:id="applicationMenusFragment">\r
<div class="btn-toolbar" style="margin: 4px 0px 0px 0px;">\r
- <div class="btn-group" wicket:id="appMenus">\r
+ <div class="btn-group tooltipped tooltipped-w" wicket:id="appMenus">\r
<span wicket:id="appMenu"></span>\r
</div>\r
</div>\r
\r
<!-- JavaScript automatic copy to clipboard -->\r
<wicket:fragment wicket:id="clippyPanel">\r
- <img class="ctcbtn" data-clipboard-action="copy" wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard" />\r
+ <img class="ctcbtn" wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard" />\r
</wicket:fragment>\r
\r
<wicket:fragment wicket:id="workingCopyFragment">\r
--- /dev/null
+// 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);
+}
+
+
+function findTooltipped(elem) {
+ do {
+ if (elem.classList.contains('tooltipped')) return elem;
+ elem = elem.parentElement;
+ } while (elem != null);
+ return null;
+}
+
+// Show or hide tooltip by setting the tooltipped-active class
+// on a parent that contains tooltipped. Since the copy button
+// could be and image, or be hidden after clicking, the tooltipped
+// element 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');
+ }
+ }
+ else {
+ console.warn("Could not find any tooltipped element for clipboard button.", e.currentTarget);
+ }
+}
+
+// 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;
+}
font-weight: 200;\r
font-size: 1em;\r
font-variant: normal;\r
-}
\ No newline at end of file
+}\r
+\r
+\r
+/*\r
+ Copy-to-clipboard tooltip styling from Github's primer.css\r
+ https://primer.style/css/components/tooltips\r
+ Adjusted to not hover but fade-in/out on clipboard events.\r
+*/\r
+\r
+.tooltipped {\r
+ position:relative\r
+}\r
+\r
+.tooltipped:after {\r
+ position: absolute;\r
+ z-index: 1000000;\r
+ padding: 5px 8px;\r
+\r
+ font: normal normal 11px/1.5 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";\r
+ color: #fff;\r
+ background: rgba(42, 42, 42, .8);\r
+ text-align: center;\r
+ text-decoration: none;\r
+ text-shadow: none;\r
+ text-transform: none;\r
+ letter-spacing: normal;\r
+ word-wrap: break-word;\r
+ white-space: pre;\r
+ pointer-events: none;\r
+ content: attr(data-tt-text);\r
+ border-radius: 3px;\r
+ -webkit-font-smoothing:subpixel-antialiased;\r
+\r
+ opacity: 0;\r
+ transition: 0.5s opacity;\r
+}\r
+\r
+.tooltipped:before {\r
+ position: absolute;\r
+ z-index: 1000001;\r
+\r
+ width: 0;\r
+ height: 0;\r
+ color: rgba(42, 42, 42, .8);\r
+ pointer-events: none;\r
+ content: "";\r
+ border:5px solid transparent;\r
+\r
+ opacity: 0;\r
+ transition: 0.5s opacity;\r
+}\r
+\r
+.tooltipped-active:before, .tooltipped-active:after {\r
+ opacity: 1;\r
+ text-decoration:none\r
+}\r
+\r
+.tooltipped-s:after, .tooltipped-se:after, .tooltipped-sw:after {\r
+ top: 100%;\r
+ right: 50%;\r
+ margin-top:5px\r
+}\r
+\r
+.tooltipped-s:before, .tooltipped-se:before, .tooltipped-sw:before {\r
+ top: auto;\r
+ right: 50%;\r
+ bottom: -5px;\r
+ margin-right: -5px;\r
+ border-bottom-color:rgba(42, 42, 42, .8)\r
+}\r
+\r
+.tooltipped-se:after {\r
+ right: auto;\r
+ left: 50%;\r
+ margin-left:-15px\r
+}\r
+\r
+.tooltipped-sw:after {\r
+ margin-right:-15px\r
+}\r
+\r
+.tooltipped-n:after, .tooltipped-ne:after, .tooltipped-nw:after {\r
+ right: 50%;\r
+ bottom: 100%;\r
+ margin-bottom:5px\r
+}\r
+\r
+.tooltipped-n:before, .tooltipped-ne:before, .tooltipped-nw:before {\r
+ top: -5px;\r
+ right: 50%;\r
+ bottom: auto;\r
+ margin-right: -5px;\r
+ border-top-color:rgba(42, 42, 42, .8)\r
+}\r
+\r
+.tooltipped-ne:after {\r
+ right: auto;\r
+ left: 50%;\r
+ margin-left:-15px\r
+}\r
+\r
+.tooltipped-nw:after {\r
+ margin-right:-15px\r
+}\r
+\r
+.tooltipped-s:after, .tooltipped-n:after {\r
+ -webkit-transform: translateX(50%);\r
+ -ms-transform: translateX(50%);\r
+ transform:translateX(50%)\r
+}\r
+\r
+.tooltipped-w:after {\r
+ right: 100%;\r
+ bottom: 50%;\r
+ margin-right: 5px;\r
+ -webkit-transform: translateY(50%);\r
+ -ms-transform: translateY(50%);\r
+ transform:translateY(50%)\r
+}\r
+\r
+.tooltipped-w:before {\r
+ top: 50%;\r
+ bottom: 50%;\r
+ left: -5px;\r
+ margin-top: -5px;\r
+ border-left-color:rgba(42, 42, 42, .8)\r
+}\r
+\r
+.tooltipped-e:after {\r
+ bottom: 50%;\r
+ left: 100%;\r
+ margin-left: 5px;\r
+ -webkit-transform: translateY(50%);\r
+ -ms-transform: translateY(50%);\r
+ transform:translateY(50%)\r
+}\r
+\r
+.tooltipped-e:before {\r
+ top: 50%;\r
+ right: -5px;\r
+ bottom: 50%;\r
+ margin-top: -5px;\r
+ border-right-color:rgba(42, 42, 42, .8)\r
+}\r
+\r
+\r
+.tooltipped-sticky:before, .tooltipped-sticky:after {\r
+ display:inline-block\r
+}\r
+\r
+\r
+.fullscreen-overlay-enabled.dark-theme .tooltipped:after {\r
+ color: #000;\r
+ background:rgba(200, 200, 200, .8)\r
+}\r
+\r
+.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 {\r
+ border-bottom-color:rgba(200, 200, 200, .8)\r
+}\r
+\r
+.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 {\r
+ border-top-color:rgba(200, 200, 200, .8)\r
+}\r
+\r
+.fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-e:before {\r
+ border-right-color:rgba(200, 200, 200, .8)\r
+}\r
+\r
+.fullscreen-overlay-enabled.dark-theme .tooltipped.tooltipped-w:before {\r
+ border-left-color:rgba(200, 200, 200, .8)\r
+}\r