triple-dots
Version:
Triple dots is a javascript plugin for truncating multiple line content with an ellipsis.
1 lines • 5.84 kB
JavaScript
export default class TripleDots{constructor(t,e=TripleDots.options){this.container=t,this.options=e||{},this.watchTimeout=null,this.watchInterval=null,this.resizeEvent=null;for(let t in TripleDots.options)TripleDots.options.hasOwnProperty(t)&&void 0===this.options[t]&&(this.options[t]=TripleDots.options[t]);const i=this.container.tripleDots;i&&i.destroy(),this.API={},["truncate","restore","destroy","watch","unwatch"].forEach((t=>{this.API[t]=()=>this[t].call(this)})),this.container.tripleDots=this.API,this.originalStyle=this.container.getAttribute("style")||"",this.originalContent=this._getOriginalContent(),this.ellipsis=document.createTextNode(this.options.ellipsis);const n=window.getComputedStyle(this.container);"break-word"!==n["word-wrap"]&&(this.container.style["word-wrap"]="break-word"),"pre"===n["white-space"]?this.container.style["white-space"]="pre-wrap":"nowrap"===n["white-space"]&&(this.container.style["white-space"]="normal"),null===this.options.height&&(this.options.height=this._getMaxHeight()),this.expanded=!1,this.isClamped=!1,this.truncate(),this.options.watch&&this.watch()}restore(){this.unwatch(),this.container.setAttribute("style",this.originalStyle),this.container.classList.remove("ddd-truncated"),this.container.innerHTML="",this.originalContent.forEach((t=>{this.container.append(t)})),this.expanded=!1}destroy(){this.restore(),this.container.tripleDots=null}watch(){this.unwatch();let t={width:null,height:null},e=(e,i,n)=>{if(this.container.offsetWidth||this.container.offsetHeight||this.container.getClientRects().length){let o={width:e[i],height:e[n]};return t.width==o.width&&t.height==o.height||this.truncate(),o}return t};"window"===this.options.watch?(this.resizeEvent=i=>{this.watchTimeout&&clearTimeout(this.watchTimeout),this.watchTimeout=setTimeout((()=>{t=e(window,"innerWidth","innerHeight")}),100)},window.addEventListener("resize",this.resizeEvent)):this.watchInterval=setInterval((()=>{t=e(this.container,"clientWidth","clientHeight")}),1e3)}unwatch(){this.resizeEvent&&(window.removeEventListener("resize",this.resizeEvent),this.resizeEvent=null),this.watchInterval&&clearInterval(this.watchInterval),this.watchTimeout&&clearTimeout(this.watchTimeout)}truncate(){let t=!1;return this.expanded=!1,this.container.innerHTML="",this.originalContent.forEach((t=>{this.container.append(t.cloneNode(!0))})),this.maxHeight=this._getMaxHeight(),this._fits()||(t=!0,this.expanded=!0,this._truncateToNode(this.container)),this.container.classList[t?"add":"remove"]("ddd-truncated"),this.options.callback.call(this.container,t),t}_truncateToNode(t){const e=[],i=[];if(TripleDots.$.contents(t).forEach((t=>{if(1!=t.nodeType||!t.matches(".ddd-keep")){let n=document.createComment("");t.replaceWith(n),i.push(t),e.push(n)}})),!i.length)return;for(var n=0;n<i.length;n++){e[n].replaceWith(i[n]);let t=this.ellipsis.cloneNode(!0);switch(i[n].nodeType){case 1:i[n].append(t);break;case 3:i[n].after(t)}let o=this._fits();if(t.parentElement.removeChild(t),!o){if("node"==this.options.truncate&&n>1)return void i[n-2].remove();break}}for(var o=n;o<e.length;o++)e[o].remove();let s=i[Math.max(0,Math.min(n,i.length-1))];if(1==s.nodeType){let t=document.createElement(s.nodeName);t.append(this.ellipsis),this.isClamped=!0,s.replaceWith(t),this._fits()?t.replaceWith(s):(t.remove(),s=i[Math.max(0,n-1)])}1==s.nodeType?this._truncateToNode(s):this._truncateToWord(s)}_truncateToWord(t){const e=t.textContent,i=-1!==e.indexOf(" ")?" ":" ",n=e.split(i);for(let e=n.length;e>=0;e--)if(t.textContent=this._addEllipsis(n.slice(0,e).join(i)),this._fits()){"letter"==this.options.truncate&&(t.textContent=n.slice(0,e+1).join(i),this._truncateToLetter(t));break}}_truncateToLetter(t){let e=t.textContent.split(""),i="";for(let n=e.length;n>=0&&(i=e.slice(0,n).join(""),!i.length||(t.textContent=this._addEllipsis(i),!this._fits()));n--);}_fits(){const t=this.maxHeight+this.options.tolerance;return this.container.scrollHeight<=t}_addEllipsis(t){const e=[" "," ",",",";",".","!","?"];for(;e.indexOf(t.slice(-1))>-1;)t=t.slice(0,-1);return t+=this.ellipsis.textContent}_getOriginalContent(){let t="script, style";this.options.keep&&(t+=", "+this.options.keep),TripleDots.$.find(t,this.container).forEach((t=>{t.classList.add("ddd-keep")}));let e="div, section, article, header, footer, p, h1, h2, h3, h4, h5, h6, table, td, td, dt, dd, li";[this.container,...TripleDots.$.find("*",this.container)].forEach((t=>{t.normalize(),TripleDots.$.contents(t).forEach((e=>{8==e.nodeType&&t.removeChild(e)})),TripleDots.$.contents(t).forEach((i=>{if(3==i.nodeType&&""==i.textContent.trim()){let n=i.previousSibling,o=i.nextSibling;(i.parentElement.matches("table, thead, tbody, tfoot, tr, dl, ul, ol, video")||!n||1==n.nodeType&&n.matches(e)||!o||1==o.nodeType&&o.matches(e))&&t.removeChild(i)}}))}));let i=[];return TripleDots.$.contents(this.container).forEach((t=>{i.push(t.cloneNode(!0))})),i}_getMaxHeight(){if("number"==typeof this.options.height)return this.options.height;const t=window.getComputedStyle(this.container);let e=["maxHeight","height"],i=0;for(let n=0;n<e.length;n++){let o=t[e[n]];if("px"==o.slice(-2)){i=parseFloat(o);break}}if("border-box"==t.boxSizing){e=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"];for(let n=0;n<e.length;n++){let o=t[e[n]];"px"==o.slice(-2)&&(i-=parseFloat(o))}}return Math.max(i,0)}}TripleDots.version="0.0.3",TripleDots.options={ellipsis:"… ",callback:function(){},truncate:"word",tolerance:0,keep:null,watch:"window",height:null},TripleDots.$={find:(t,e)=>(e=e||document,Array.prototype.slice.call(e.querySelectorAll(t))),contents:t=>(t=t||document,Array.prototype.slice.call(t.childNodes))},function(t){void 0!==t&&(t.fn.tripleDots=function(t){return this.each(((e,i)=>{let n=new TripleDots(i,t);i.tripleDots=n.API}))})}(window.Zepto||window.jQuery);