Improve the clipboard UX

This commit is contained in:
Cotes Chung 2021-09-15 14:36:37 +08:00
parent 2877896b9e
commit 53b0329e5a
7 changed files with 66 additions and 19 deletions

View file

@ -116,7 +116,7 @@
{% capture _tag_head %}<div class="language-{% endcapture %} {% capture _tag_head %}<div class="language-{% endcapture %}
{% assign _replacement = '-rouge"><div class="code-header" data-lang="' {% assign _replacement = '-rouge"><div class="code-header" data-lang="'
| append: _lang | append: _lang
| append: '"><button><i class="fa-fw far fa-clipboard"></i></button></div><div class="highlight">' | append: '"><button><i class="far fa-clone"></i></button></div><div class="highlight">'
%} %}
{% capture _tag_tail %}{{ _snippet | replace: '-rouge"><div class="highlight">', _replacement }}{% endcapture %} {% capture _tag_tail %}{{ _snippet | replace: '-rouge"><div class="highlight">', _replacement }}{% endcapture %}
{% assign _new_content = _new_content | append: _tag_head | append: _tag_tail %} {% assign _new_content = _new_content | append: _tag_head | append: _tag_tail %}

View file

@ -1,19 +1,29 @@
/* /*
* Initial the clipboard.js object, see: <https://github.com/zenorocha/clipboard.js> * Initial the clipboard.js object
* *
* Dependencies: * Dependencies:
* - popper.js (https://github.com/popperjs/popper-core) * - popper.js (https://github.com/popperjs/popper-core)
* - clipboard.js (https://github.com/zenorocha/clipboard.js) * - clipboard.js (https://github.com/zenorocha/clipboard.js)
*/ */
$(function() { $(function() {
const btnSelector = '.code-header>button'; const btnSelector = '.code-header>button';
const ICON_DEFAULT = getIcon(btnSelector);
const ICON_SUCCESS = 'fas fa-check';
const ATTR_LOCKED = 'locked';
const TIMEOUT = 2000; // in milliseconds
var clipboard = new ClipboardJS(btnSelector, { const clipboard = new ClipboardJS(btnSelector, {
target(trigger) { target(trigger) {
return trigger.parentNode.nextElementSibling; return trigger.parentNode.nextElementSibling;
} }
}); });
$(btnSelector).tooltip({
trigger: 'click',
placement: 'left'
});
function setTooltip(btn, msg) { function setTooltip(btn, msg) {
$(btn).tooltip('hide') $(btn).tooltip('hide')
.attr('data-original-title', msg) .attr('data-original-title', msg)
@ -23,18 +33,49 @@ $(function() {
function hideTooltip(btn) { function hideTooltip(btn) {
setTimeout(function() { setTimeout(function() {
$(btn).tooltip('hide'); $(btn).tooltip('hide');
}, 1000); }, TIMEOUT);
} }
$(btnSelector).tooltip({ function getIcon(btn) {
trigger: 'click', let iconNode = $(btn).children();
placement: 'left' return iconNode.attr('class');;
}); }
clipboard.on('success', function(e) { function setSuccessIcon(btn) {
let btnNode = $(btn);
let iconNode = btnNode.children();
btnNode.attr(ATTR_LOCKED, true);
iconNode.attr('class', ICON_SUCCESS);
}
function resumeIcon(btn) {
let btnNode = $(btn);
let iconNode = btnNode.children();
setTimeout(function() {
btnNode.removeAttr(ATTR_LOCKED);
iconNode.attr('class', ICON_DEFAULT);
}, TIMEOUT);
}
function isLocked(btn) {
let locked = $(btn).attr(ATTR_LOCKED);
return locked === 'true';
}
clipboard.on('success', (e) => {
e.clearSelection(); e.clearSelection();
if (isLocked(e.trigger)) {
return;
}
setTooltip(e.trigger, 'Copied!'); setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger); hideTooltip(e.trigger);
setSuccessIcon(e.trigger);
resumeIcon($(e.trigger));
}); });
}); });

View file

@ -184,12 +184,19 @@ div {
// clipboard // clipboard
button { button {
border: 0; border: 1px solid var(--code-header-bg);
border-radius: $code-radius;
padding: 0;
width: 1.95rem;
background-color: inherit; background-color: inherit;
border-top-right-radius: $code-radius;
color: var(--highlight-lineno-color); color: var(--highlight-lineno-color);
&:hover { &[locked=true] {
color: var(--clipboard-checked-color);
border-color: var(--clipboard-checked-color);
}
&:not([locked]):hover {
background-color: gray; background-color: gray;
color: white; color: white;
} }
@ -199,7 +206,7 @@ div {
} }
i { i {
font-size: 85%; font-size: 0.9rem;
} }
} }
@ -216,10 +223,7 @@ div {
.code-header { .code-header {
border-radius: 0; border-radius: 0;
padding-left: 0.4rem; padding-left: 0.4rem;
padding-right: 0.5rem;
button {
border-top-right-radius: 0;
}
} }
} }
} }

View file

@ -76,6 +76,7 @@
--inline-code-bg: #272822; --inline-code-bg: #272822;
--code-header-bg: #353535; --code-header-bg: #353535;
--lang-badge-color: #6c6c6d; --lang-badge-color: #6c6c6d;
--clipboard-checked-color: #2bcc2b;
.highlight { .highlight {
.gp { color: #818c96; } .gp { color: #818c96; }

View file

@ -73,5 +73,6 @@
--inline-code-bg: #f3f3f3; --inline-code-bg: #f3f3f3;
--code-header-bg: #eaeaea; --code-header-bg: #eaeaea;
--lang-badge-color: #a4a7ab; --lang-badge-color: #a4a7ab;
--clipboard-checked-color: #43c743;
} // light-syntax } // light-syntax

View file

@ -3,4 +3,4 @@
* © 2019 Cotes Chung * © 2019 Cotes Chung
* MIT Licensed * MIT Licensed
*/ */
$(function(){$(window).scroll(()=>{$(this).scrollTop()>50&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),s=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),i=$("#search-result-wrapper"),r=$("#search-results"),d=$("#search-input"),c=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset:()=>e}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),t.addClass("unloaded"),n.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),t.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),i.removeClass("unloaded"),s.addClass("unloaded"),e=!0)},off(){e&&(r.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),i.addClass("unloaded"),a.removeClass("visible"),s.removeClass("unloaded"),u.release(),d.val(""),e=!1)},isVisible:()=>e}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),f.on(),d.focus()}),o.click(function(){p.off(),f.off()}),d.focus(function(){n.addClass("input-focus")}),d.focusout(function(){n.removeClass("input-focus")}),d.on("keyup",function(e){8===e.keyCode&&""===d.val()?h()?c.removeClass("unloaded"):f.off():""!==d.val()&&(f.on(),a.hasClass("visible")||a.addClass("visible"),h()&&c.addClass("unloaded"))}),a.on("click",function(){d.val(""),h()?(c.removeClass("unloaded"),r.empty()):f.off(),d.focus(),a.removeClass("visible")})}),$(function(){const e=function(){let e=!1;const t=$("body");return{toggle(){!1===e?t.attr("sidebar-display",""):t.removeAttr("sidebar-display"),e=!e}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),t=$("#toc-wrapper"),o=$(".access"),a=$("#search-input");let s,l=0;const n=5,i=e.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(s=!0)}),setInterval(function(){s&&(!function(){var s=$(this).scrollTop();Math.abs(l-s)<=n||(s>l&&s>i?(e.removeClass("topbar-down").addClass("topbar-up"),t.length>0&&t.removeClass("topbar-down"),o.length>0&&o.removeClass("topbar-down"),a.is(":focus")&&a.blur()):s+$(window).height()<$(document).height()&&(e.removeClass("topbar-up").addClass("topbar-down"),t.length>0&&t.addClass("topbar-down"),o.length>0&&o.addClass("topbar-down")),l=s)}(),s=!1)},250)}),$(function(){const e=$("#topbar-title"),t=$("div.post>h1"),o=e.text().trim();let a=t.length>0?t.text().trim():$("h1").text().trim();($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),$(window).scroll(function(){if($("#post-list").length||t.is(":hidden")||e.is(":hidden")||$("#sidebar.sidebar-expand").length)return!1;$(this).scrollTop()>=95?e.text()!==a&&e.text(a):e.text()!==o&&e.text(o)}),e.click(function(){$("body,html").animate({scrollTop:0},800)})}),$(function(){$("input[type=checkbox]").addClass("unloaded"),$("input[type=checkbox][checked]").before('<i class="fas fa-check-circle checked"></i>'),$("input[type=checkbox]:not([checked])").before('<i class="far fa-circle"></i>')}),$(function(){const e="#main > div.row:first-child > div:first-child";if($(`${e} img`).length<=0)return;const t=document.querySelectorAll(`${e} img[data-src]`);lozad(t).observe(),$(`${e} p > img[data-src],${e} img[data-src].preview-img`).each(function(){let e=$(this).next();const t="EM"===e.prop("tagName")?e.text():"",o=$(this).attr("data-src");$(this).wrap(`<a href="${o}" title="${t}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(`${e} a`).has("img").addClass("img-link")}),$(function(){var e=new ClipboardJS(".code-header>button",{target:e=>e.parentNode.nextElementSibling});$(".code-header>button").tooltip({trigger:"click",placement:"left"}),e.on("success",function(e){var t,o;e.clearSelection(),t=e.trigger,o="Copied!",$(t).tooltip("hide").attr("data-original-title",o).tooltip("show"),function(e){setTimeout(function(){$(e).tooltip("hide")},1e3)}(e.trigger)})}); $(function(){$(window).scroll(()=>{$(this).scrollTop()>50&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),s=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),i=$("#search-result-wrapper"),r=$("#search-results"),c=$("#search-input"),d=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset:()=>e}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),t.addClass("unloaded"),n.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),t.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),i.removeClass("unloaded"),s.addClass("unloaded"),e=!0)},off(){e&&(r.empty(),d.hasClass("unloaded")&&d.removeClass("unloaded"),i.addClass("unloaded"),a.removeClass("visible"),s.removeClass("unloaded"),u.release(),c.val(""),e=!1)},isVisible:()=>e}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),f.on(),c.focus()}),o.click(function(){p.off(),f.off()}),c.focus(function(){n.addClass("input-focus")}),c.focusout(function(){n.removeClass("input-focus")}),c.on("keyup",function(e){8===e.keyCode&&""===c.val()?h()?d.removeClass("unloaded"):f.off():""!==c.val()&&(f.on(),a.hasClass("visible")||a.addClass("visible"),h()&&d.addClass("unloaded"))}),a.on("click",function(){c.val(""),h()?(d.removeClass("unloaded"),r.empty()):f.off(),c.focus(),a.removeClass("visible")})}),$(function(){const e=function(){let e=!1;const t=$("body");return{toggle(){!1===e?t.attr("sidebar-display",""):t.removeAttr("sidebar-display"),e=!e}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),t=$("#toc-wrapper"),o=$(".access"),a=$("#search-input");let s,l=0;const n=5,i=e.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(s=!0)}),setInterval(function(){s&&(!function(){var s=$(this).scrollTop();Math.abs(l-s)<=n||(s>l&&s>i?(e.removeClass("topbar-down").addClass("topbar-up"),t.length>0&&t.removeClass("topbar-down"),o.length>0&&o.removeClass("topbar-down"),a.is(":focus")&&a.blur()):s+$(window).height()<$(document).height()&&(e.removeClass("topbar-up").addClass("topbar-down"),t.length>0&&t.addClass("topbar-down"),o.length>0&&o.addClass("topbar-down")),l=s)}(),s=!1)},250)}),$(function(){const e=$("#topbar-title"),t=$("div.post>h1"),o=e.text().trim();let a=t.length>0?t.text().trim():$("h1").text().trim();($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),$(window).scroll(function(){if($("#post-list").length||t.is(":hidden")||e.is(":hidden")||$("#sidebar.sidebar-expand").length)return!1;$(this).scrollTop()>=95?e.text()!==a&&e.text(a):e.text()!==o&&e.text(o)}),e.click(function(){$("body,html").animate({scrollTop:0},800)})}),$(function(){$("input[type=checkbox]").addClass("unloaded"),$("input[type=checkbox][checked]").before('<i class="fas fa-check-circle checked"></i>'),$("input[type=checkbox]:not([checked])").before('<i class="far fa-circle"></i>')}),$(function(){const e="#main > div.row:first-child > div:first-child";if($(`${e} img`).length<=0)return;const t=document.querySelectorAll(`${e} img[data-src]`);lozad(t).observe(),$(`${e} p > img[data-src],${e} img[data-src].preview-img`).each(function(){let e=$(this).next();const t="EM"===e.prop("tagName")?e.text():"",o=$(this).attr("data-src");$(this).wrap(`<a href="${o}" title="${t}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(`${e} a`).has("img").addClass("img-link")}),$(function(){const e=$(".code-header>button").children().attr("class");const t="fas fa-check",o="locked",a=2e3,s=new ClipboardJS(".code-header>button",{target:e=>e.parentNode.nextElementSibling});$(".code-header>button").tooltip({trigger:"click",placement:"left"}),s.on("success",s=>{s.clearSelection(),function(e){return"true"===$(e).attr(o)}(s.trigger)||(function(e,t){$(e).tooltip("hide").attr("data-original-title",t).tooltip("show")}(s.trigger,"Copied!"),function(e){setTimeout(function(){$(e).tooltip("hide")},a)}(s.trigger),function(e){let a=$(e),s=a.children();a.attr(o,!0),s.attr("class",t)}(s.trigger),function(t){let s=$(t),l=s.children();setTimeout(function(){s.removeAttr(o),l.attr("class",e)},a)}($(s.trigger)))})});

File diff suppressed because one or more lines are too long