feat: add copy button
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-01-11 10:48:20 +08:00
parent 17fbb2c910
commit 8b2de39c5f
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
5 changed files with 58 additions and 15 deletions

View File

@ -168,7 +168,9 @@ if ($perm['manager_view']) {
?> ?>
<?php if ($perm['content'] || $perm['manager_view']) : ?> <?php if ($perm['content'] || $perm['manager_view']) : ?>
<div class="copy-button-container">
<?php UOJSubmission::cur()->echoContent() ?> <?php UOJSubmission::cur()->echoContent() ?>
</div>
<?php if (isset($hack_form)) : ?> <?php if (isset($hack_form)) : ?>
<p class="text-center"> <p class="text-center">
@ -221,17 +223,17 @@ if (UOJSubmission::cur()->hasJudged()) {
?> ?>
<div class="d-flex gap-2 justify-content-end"> <div class="d-flex gap-2 justify-content-end">
<?php if (isset($minor_rejudge_form)) : ?> <?php if (isset($minor_rejudge_form)) : ?>
<?php $minor_rejudge_form->printHTML() ?> <?php $minor_rejudge_form->printHTML() ?>
<?php endif ?> <?php endif ?>
<?php if (isset($rejudge_form)) : ?> <?php if (isset($rejudge_form)) : ?>
<?php $rejudge_form->printHTML() ?> <?php $rejudge_form->printHTML() ?>
<?php endif ?> <?php endif ?>
<?php if (isset($delete_form)) : ?> <?php if (isset($delete_form)) : ?>
<?php $delete_form->printHTML() ?> <?php $delete_form->printHTML() ?>
<?php endif ?> <?php endif ?>
</div> </div>
<?php echoUOJPageFooter() ?> <?php echoUOJPageFooter() ?>

View File

@ -4,11 +4,6 @@ if (!isset($ShowPageFooter)) {
} }
?> ?>
</div> </div>
<script>
$(document).ready(function() {
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
});
</script>
<?php if ($ShowPageFooter) : ?> <?php if ($ShowPageFooter) : ?>
<?php if (UOJNotice::shouldConstantlyCheckNotice()) : ?> <?php if (UOJNotice::shouldConstantlyCheckNotice()) : ?>
<script type="text/javascript"> <script type="text/javascript">

View File

@ -102,6 +102,9 @@ if (!isset($ShowPageHeader)) {
<!-- Color converter --> <!-- Color converter -->
<?= HTML::js_src('/js/color-converter.min.js') ?> <?= HTML::js_src('/js/color-converter.min.js') ?>
<!-- Clipboard Polyfill -->
<?= HTML::js_src('/js/clipboard-polyfill.overwrite-globals.es5.min.js') ?>
<!-- uoj --> <!-- uoj -->
<?= HTML::js_src('/js/uoj.js?v=' . UOJConfig::$data['profile']['s2oj-version']) ?> <?= HTML::js_src('/js/uoj.js?v=' . UOJConfig::$data['profile']['s2oj-version']) ?>

View File

@ -0,0 +1,2 @@
/*! clipboard-polyfill v4.0.0-rc8 | MIT License | github.com/zenorocha/clipboard.js */
"use strict";!function(){var e="text/plain";(function(){(console.warn||console.log).apply(console,arguments)}).bind("[clipboard-polyfill]");var n,t,r,o="undefined"==typeof window?void 0:window,i="undefined"==typeof globalThis?void 0:globalThis,a=null!=(r=null==(n=o)?void 0:n.Promise)?r:null==(t=i)?void 0:t.Promise;var u,l,c,d,f,v="undefined"==typeof navigator?void 0:navigator,s=null==v?void 0:v.clipboard,p=null==(u=null==s?void 0:s.read)?void 0:u.bind(s),b=null==(l=null==s?void 0:s.readText)?void 0:l.bind(s),m=null==(c=null==s?void 0:s.write)?void 0:c.bind(s),y=null==(d=null==s?void 0:s.writeText)?void 0:d.bind(s),w=null==(f=o)?void 0:f.ClipboardItem,h=function(){if(!a)throw new Error("No `Promise` implementation available for `clipboard-polyfill`. Consider using: https://github.com/lgarron/clipboard-polyfill#flat-file-version-with-promise-included");return a}(),g=o;function x(){return"undefined"==typeof ClipboardEvent&&void 0!==(null==g?void 0:g.clipboardData)&&void 0!==(null==g?void 0:g.clipboardData.setData)}function E(n,t,r){for(var o in n.success=!0,t){var i=t[o],a=r.clipboardData;a.setData(o,i),o===e&&a.getData(o)!==i&&(n.success=!1)}r.preventDefault()}function C(e){var n={success:!1},t=E.bind(this,n,e);document.addEventListener("copy",t);try{document.execCommand("copy")}finally{document.removeEventListener("copy",t)}return n.success}function T(e,n){D(e);var t=C(n);return S(),t}function D(e){var n=document.getSelection();if(n){var t=document.createRange();t.selectNodeContents(e),n.removeAllRanges(),n.addRange(t)}}function S(){var e=document.getSelection();e&&e.removeAllRanges()}function A(n){var t,r=e in n;if(x()){if(!r)throw new Error("No `text/plain` value was specified.");if(t=n[e],g.clipboardData.setData("Text",t))return!0;throw new Error("Copying failed, possibly because the user rejected it.")}return!!C(n)||(navigator.userAgent.indexOf("Edge")>-1||(!!T(document.body,n)||(!!function(e){var n=document.createElement("div");n.setAttribute("style","-webkit-user-select: text !important"),n.textContent="temporary element",document.body.appendChild(n);var t=T(n,e);return document.body.removeChild(n),t}(n)||!!function(e){var n=document.createElement("div");n.setAttribute("style","-webkit-user-select: text !important");var t=n;n.attachShadow&&(t=n.attachShadow({mode:"open"}));var r=document.createElement("span");r.innerText=e,t.appendChild(r),document.body.appendChild(n),D(r);var o=document.execCommand("copy");return S(),document.body.removeChild(n),o}(n[e]))))}function R(e,n){var t=[];for(var r in e){var o=e[r];t.push(n(o))}return h.all(t).then((function(n){for(var t={},r=0;r<e.length;r++)t[e[r]]=n[r];return t}))}var k=h.resolve(),L=function(){return h.resolve(!0)},N=h.resolve(!1);function O(e){return new h((function(n,t){try{n(e())}catch(e){t(e)}}))}function P(n){if(!A(function(n){var t={};return t[e]=n,t}(n)))throw new Error("writeText() failed")}function j(){return O((function(){if(b)return b();if(x()){var e=function(){var e=g.clipboardData.getData("Text");if(""===e)throw new Error("Empty clipboard or could not read plain text from clipboard");return e}();return h.resolve(e)}throw new Error("Read is not supported in your browser.")}))}function I(e,n){for(var t in e){if(-1!==e[t].types.indexOf(n))return!0}return!1}var B=function(e,n){var t,r=Object.keys(e),o={};for(var i in e){var a=e[i];o[i]="string"==typeof a?F(i,a):a}return{types:r,presentationStyle:null!=(t=null==n?void 0:n.presentationStyle)?t:"unspecified",getType:function(e){return h.resolve(o[e])}}};function F(e,n){return new Blob([n],{type:e})}function q(e){return R(e.types,(function(n){return e.getType(n)})).then((function(n){var t={};return e.presentationStyle&&(t.presentationStyle=e.presentationStyle),new w(n,t)}))}function z(n){var t={};return t[e]=F(n,e),new B(t)}function G(e,n){return e.getType(n).then((function(e){return n=e,new h((function(e,t){var r=new FileReader;r.addEventListener("load",(function(){var n=r.result;"string"==typeof n?e(n):t("could not convert blob to string")})),r.readAsText(n)}));var n}))}navigator.clipboard||(navigator.clipboard={}),navigator.clipboard.read=function(){return O((function(){return p?p():j().then((function(e){return[z(e)]}))}))},navigator.clipboard.readText=j,navigator.clipboard.write=function(n){return O((function(){if(m&&w){var t=m;return h.all(n.map(q)).then((function(r){return t(r).then(L).catch((function(t){if(!I(n,e)&&!I(n,"text/html"))throw t;return N}))}))}return N})).then((function(t){if(t)return k;I(n,e);return function(e){return R(e.types,(function(n){return G(e,n)}))}(n[0]).then((function(e){if(!A(e))throw new Error("write() failed")}))}))},navigator.clipboard.writeText=function(e){return O((function(){return y?y(e).catch(P):h.resolve(P(e))}))},window.ClipboardItem=B}();

View File

@ -1103,3 +1103,44 @@ function showCommentReplies(id, replies) {
} }
); );
} }
// Tooltip
$(document).ready(function() {
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
});
// Copy button
$(document).ready(function() {
$('.markdown-body pre, .copy-button-container pre').each(function () {
var thisEl = $(this);
$(this).wrap(
$('<div class="wrapped-copy-button-container" style="position: relative;"></div>')
).parent().prepend(
$(
'<div style="position: absolute; right: 0; top: 0; margin-top: 0.75rem; margin-right: 0.75rem; font-size: 0.85em;"></div>'
).append(
$('<button style="position: relative; background: transparent; border: 0;"></button>')
.click(function () {
navigator.clipboard
.writeText($(thisEl).text())
.then(() => {
$(this).html('<i class="bi bi-check2 text-success"></i>');
setTimeout(() => {
$(this).html('<i class="bi bi-clipboard text-muted"></i>');
}, 1000);
})
.catch(() => {
$(this).html('<i class="bi bi-x-lg text-danger"></i>');
setTimeout(() => {
$(this).html('<i class="bi bi-clipboard text-muted"></i>');
}, 1000);
});
})
.append('<i class="bi bi-clipboard text-muted"></i>')
)
);
});
});