diff options
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/RepositoryPage.java | 5 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/SummaryPage.html | 7 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html | 10 | ||||
-rw-r--r-- | src/main/resources/clipboard/gitblit-ctcbtn.js | 74 | ||||
-rw-r--r-- | src/main/resources/gitblit.css | 172 |
5 files changed, 256 insertions, 12 deletions
diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java index 4d30e049..b30aee97 100644 --- a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java @@ -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);
}
diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html b/src/main/java/com/gitblit/wicket/pages/SummaryPage.html index b6afc301..8915ecf5 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.html @@ -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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html index 1cadd7d5..e4b7427a 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html @@ -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">
diff --git a/src/main/resources/clipboard/gitblit-ctcbtn.js b/src/main/resources/clipboard/gitblit-ctcbtn.js new file mode 100644 index 00000000..ddb2ddad --- /dev/null +++ b/src/main/resources/clipboard/gitblit-ctcbtn.js @@ -0,0 +1,74 @@ +// 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; +} diff --git a/src/main/resources/gitblit.css b/src/main/resources/gitblit.css index f7271788..bd2befd3 100644 --- a/src/main/resources/gitblit.css +++ b/src/main/resources/gitblit.css @@ -2408,4 +2408,174 @@ table.filestore-status { font-weight: 200;
font-size: 1em;
font-variant: normal;
-}
\ No newline at end of file +}
+
+
+/*
+ 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)
+}
|