This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use.
Author Image Thursday, 7 June 2018

[Version 2] Tạo khung chứa code có nút copy to clipboard cho blogspot


Trong bài viết Tạo khung chứa code có nút copy to clipboard cho blogspot chúng ta đã tạo được một form rất chuyên nghiệp để chia sẻ code, tuy nhiên nhận thấy vẫn có nhiều bất tiện trong quá trình sử dụng, để khắc phục điều đó chúng ta sẽ nâng cấp lên version 2 dễ sử dụng hơn sẽ được trình bày chi tiết trong bài viết này.

Những bất cập ở version cũ
  • Form trình bày code khi viết bài quá dài, hầu như khi viết bài tôi lại phải lục lại code
  • Rất mất thời gian chỉnh từng id để copy đúng nội dung
  • Mất thời gian nâng cấp icon font từ 4 lên 5 vì code font nằm trong bài viết

Xem demo

 DEMO

Công cụ để tạo nên khung code này
  • jQuery
  • Font Awesome
  • ClipboardJS
  • Tooltip Bootstrap component

Bài viết sử dụng jQuery 3.3.1, Font Awesome 5, ClipboardJS 2.0.1 và Tooltip Bootstrap 3.3.7

Tích hợp CSS tooltip và CSS khung chứa code

.codeHeader{background-color:#f5f5f5;border:1px solid #e0e0e0;border-bottom:0;text-align:right;padding:6px 0}
.copy-text{font-size:14px;cursor:pointer;color:#707070;padding:7px 10px;border-left:1px solid #e0e0e0}
.copy-text:before{font-family:"font awesome 5 free";content:"\f24d";display:inline-block;margin-right:7px}
.copy-text:hover{color:#707070;background:#ccc}
pre copy{display:block;background:#f9f9f9;max-height:400px;font-size:14px;color:black;text-align:left;overflow:auto;border:1px solid #d3d6db;margin:auto;padding:16px;line-height:21px}
.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}
.tooltip.in{opacity:.9;filter:alpha(opacity=90)}
.tooltip.top{padding:5px 0;margin-top:-3px}
.tooltip.right{padding:0 5px;margin-left:3px}
.tooltip.bottom{padding:5px 0;margin-top:3px}
.tooltip.left{padding:0 5px;margin-left:-3px}
.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}
.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}
.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}
.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}
.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}
.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}

Tích hợp jQuery, Font Awesome 5, chèn code trước thẻ </head> (bỏ qua nếu đã tích hợp)

<link href='https://use.fontawesome.com/releases/v5.0.13/css/all.css' rel='stylesheet' type='text/css' />
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'/>

Tích hợp ClipboardJS và Tooltip chèn code trước thẻ đóng </body>

<script src='https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.1/clipboard.min.js'/>
<script type='text/javascript'>//<![CDATA[
/* ========================================================================
 * Bootstrap: tooltip.js v3.3.7
 * http://getbootstrap.com/javascript/#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */
!function(t){"use strict";var e=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};e.VERSION="3.3.7",e.TRANSITION_DURATION=150,e.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},e.prototype.init=function(e,i,o){if(this.enabled=!0,this.type=e,this.$element=t(i),this.options=this.getOptions(o),this.$viewport=this.options.viewport&&t(t.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var n=this.options.trigger.split(" "),s=n.length;s--;){var r=n[s];if("click"==r)this.$element.on("click."+this.type,this.options.selector,t.proxy(this.toggle,this));else if("manual"!=r){var l="hover"==r?"mouseenter":"focusin",a="hover"==r?"mouseleave":"focusout";this.$element.on(l+"."+this.type,this.options.selector,t.proxy(this.enter,this)),this.$element.on(a+"."+this.type,this.options.selector,t.proxy(this.leave,this))}}this.options.selector?this._options=t.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},e.prototype.getDefaults=function(){return e.DEFAULTS},e.prototype.getOptions=function(e){return(e=t.extend({},this.getDefaults(),this.$element.data(),e)).delay&&"number"==typeof e.delay&&(e.delay={show:e.delay,hide:e.delay}),e},e.prototype.getDelegateOptions=function(){var e={},i=this.getDefaults();return this._options&&t.each(this._options,function(t,o){i[t]!=o&&(e[t]=o)}),e},e.prototype.enter=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);if(i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusin"==e.type?"focus":"hover"]=!0),i.tip().hasClass("in")||"in"==i.hoverState)i.hoverState="in";else{if(clearTimeout(i.timeout),i.hoverState="in",!i.options.delay||!i.options.delay.show)return i.show();i.timeout=setTimeout(function(){"in"==i.hoverState&&i.show()},i.options.delay.show)}},e.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},e.prototype.leave=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);if(i||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i)),e instanceof t.Event&&(i.inState["focusout"==e.type?"focus":"hover"]=!1),!i.isInStateTrue()){if(clearTimeout(i.timeout),i.hoverState="out",!i.options.delay||!i.options.delay.hide)return i.hide();i.timeout=setTimeout(function(){"out"==i.hoverState&&i.hide()},i.options.delay.hide)}},e.prototype.show=function(){var i=t.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(i);var o=t.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(i.isDefaultPrevented()||!o)return;var n=this,s=this.tip(),r=this.getUID(this.type);this.setContent(),s.attr("id",r),this.$element.attr("aria-describedby",r),this.options.animation&&s.addClass("fade");var l="function"==typeof this.options.placement?this.options.placement.call(this,s[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,p=a.test(l);p&&(l=l.replace(a,"")||"top"),s.detach().css({top:0,left:0,display:"block"}).addClass(l).data("bs."+this.type,this),this.options.container?s.appendTo(this.options.container):s.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var h=this.getPosition(),f=s[0].offsetWidth,c=s[0].offsetHeight;if(p){var u=l,d=this.getPosition(this.$viewport);l="bottom"==l&&h.bottom+c>d.bottom?"top":"top"==l&&h.top-c<d.top?"bottom":"right"==l&&h.right+f>d.width?"left":"left"==l&&h.left-f<d.left?"right":l,s.removeClass(u).addClass(l)}var g=this.getCalculatedOffset(l,h,f,c);this.applyPlacement(g,l);var m=function(){var t=n.hoverState;n.$element.trigger("shown.bs."+n.type),n.hoverState=null,"out"==t&&n.leave(n)};t.support.transition&&this.$tip.hasClass("fade")?s.one("bsTransitionEnd",m).emulateTransitionEnd(e.TRANSITION_DURATION):m()}},e.prototype.applyPlacement=function(e,i){var o=this.tip(),n=o[0].offsetWidth,s=o[0].offsetHeight,r=parseInt(o.css("margin-top"),10),l=parseInt(o.css("margin-left"),10);isNaN(r)&&(r=0),isNaN(l)&&(l=0),e.top+=r,e.left+=l,t.offset.setOffset(o[0],t.extend({using:function(t){o.css({top:Math.round(t.top),left:Math.round(t.left)})}},e),0),o.addClass("in");var a=o[0].offsetWidth,p=o[0].offsetHeight;"top"==i&&p!=s&&(e.top=e.top+s-p);var h=this.getViewportAdjustedDelta(i,e,a,p);h.left?e.left+=h.left:e.top+=h.top;var f=/top|bottom/.test(i),c=f?2*h.left-n+a:2*h.top-s+p,u=f?"offsetWidth":"offsetHeight";o.offset(e),this.replaceArrow(c,o[0][u],f)},e.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},e.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find(".tooltip-inner")[this.options.html?"html":"text"](e),t.removeClass("fade in top bottom left right")},e.prototype.hide=function(i){var o=this,n=t(this.$tip),s=t.Event("hide.bs."+this.type);function r(){"in"!=o.hoverState&&n.detach(),o.$element&&o.$element.removeAttr("aria-describedby").trigger("hidden.bs."+o.type),i&&i()}if(this.$element.trigger(s),!s.isDefaultPrevented())return n.removeClass("in"),t.support.transition&&n.hasClass("fade")?n.one("bsTransitionEnd",r).emulateTransitionEnd(e.TRANSITION_DURATION):r(),this.hoverState=null,this},e.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},e.prototype.hasContent=function(){return this.getTitle()},e.prototype.getPosition=function(e){var i=(e=e||this.$element)[0],o="BODY"==i.tagName,n=i.getBoundingClientRect();null==n.width&&(n=t.extend({},n,{width:n.right-n.left,height:n.bottom-n.top}));var s=window.SVGElement&&i instanceof window.SVGElement,r=o?{top:0,left:0}:s?null:e.offset(),l={scroll:o?document.documentElement.scrollTop||document.body.scrollTop:e.scrollTop()},a=o?{width:t(window).width(),height:t(window).height()}:null;return t.extend({},n,l,a,r)},e.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},e.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,r=this.getPosition(this.$viewport);if(/right|left/.test(t)){var l=e.top-s-r.scroll,a=e.top+s-r.scroll+o;l<r.top?n.top=r.top-l:a>r.top+r.height&&(n.top=r.top+r.height-a)}else{var p=e.left-s,h=e.left+s+i;p<r.left?n.left=r.left-p:h>r.right&&(n.left=r.left+r.width-h)}return n},e.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},e.prototype.getUID=function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},e.prototype.tip=function(){if(!this.$tip&&(this.$tip=t(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},e.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},e.prototype.enable=function(){this.enabled=!0},e.prototype.disable=function(){this.enabled=!1},e.prototype.toggleEnabled=function(){this.enabled=!this.enabled},e.prototype.toggle=function(e){var i=this;e&&((i=t(e.currentTarget).data("bs."+this.type))||(i=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,i))),e?(i.inState.click=!i.inState.click,i.isInStateTrue()?i.enter(i):i.leave(i)):i.tip().hasClass("in")?i.leave(i):i.enter(i)},e.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})};var i=t.fn.tooltip;t.fn.tooltip=function(i){return this.each(function(){var o=t(this),n=o.data("bs.tooltip"),s="object"==typeof i&&i;!n&&/destroy|hide/.test(i)||(n||o.data("bs.tooltip",n=new e(this,s)),"string"==typeof i&&n[i]())})},t.fn.tooltip.Constructor=e,t.fn.tooltip.noConflict=function(){return t.fn.tooltip=i,this}}(jQuery);
//]]></script>

Cuối cùng khởi tạo nút copy, tooltip cùng 1 số thành phần cần thiết,  chèn code ngay bên dưới 2 script bên trên

<script type='text/javascript'>//<![CDATA[
jQuery(document).ready(function($) {
    jQuery("pre copy").before("<div class='codeHeader'><a class='copy-text' data-clipboard-target='pre copy' data-clipboard-action='copy'>Copy</a></div>");
    $('.copy-text').tooltip({
        trigger: 'click'
    })
});
var clipboard = new ClipboardJS(".copy-text", {
    target: function(trigger) {
        return trigger.parentNode.nextElementSibling
    }
});

function setTooltip(btn, message) {
    $(btn).tooltip('hide').attr('data-original-title', message).tooltip('show');
}

function hideTooltip(btn) {
    setTimeout(function() {
        $(btn).tooltip('hide');
    }, 1000);
}
clipboard.on('success', function(e) {
    var btn = $(e.trigger);
    setTooltip(btn, 'Copied');
    hideTooltip(btn);
});
clipboard.on('error', function(e) {
    var btn = $(e.trigger);
    setTooltip('Failed');
    hideTooltip(btn);
});
//]]></script>

Lưu mẫu lại !

Khi viết bài để tạo khung code bạn chuyển chế độ HTML và đặt code theo mẫu

<pre><copy>
<!-- Dán code vào đây -->
</copy></pre>

Trước khi dán code bạn cần convert các kí tự để tránh code chạy luôn trên trang, sử dụng công cụ convert để chuyển đổi nhé

Như bạn thấy, mẫu code tạo form khi viết bài đã được rút gọn đi một cách không thể ngắn hơn nhờ 1 ít js, bên cạnh đó bạn cũng không cần chỉnh sửa data-clipboard-target nữa, icon font cũng được định nghĩa qua css, bạn có thể dễ dàng thay đổi trong template

#Lưu ý: Nếu bạn tích hợp ClipboardJS verson 1.x.x thì phải chuyển ClipboardJS thành Clipboard để code hoạt động đúng nhé

KẾT LUẬN: Khi ghé thăm các trang về thủ thuật, tôi rất thích trang nào có nút copy to clipboard rất thích quay lại trang của họ, vì đơn giản nó giảm được rất nhiều thao tác tay cũng như thể hiện được độ chuyên nghiệp của webmaster. Hi vọng khung chứa code này sẽ sớm xuất hiện trên trang của bạn

Chúc thành công !
Comments:
Bạn được tự do bày tỏ quan điểm nhưng nghiêm cấm spam
  • Chèn ảnh theo mẫu [img]link[/img]
  • Chèn video Youtube theo mẫu [youtube]link[/youtube]
  • Chèn code theo mẫu [pre]code[/pre]. Lưu ý: mã hóa code trước khi bình luận

  • Please wait while i am loading Facebook SDK js