@corgras/readmore-js
Version:
A smooth and lightweight pure JavaScript plugin for collapsing long text blocks with "Read more" and "Close" buttons, enhancing readability and saving space, perfect for mobile devices.
9 lines • 5.01 kB
JavaScript
/*!
* Readmore.js v2.2.0 - JavaScript plugin
* Author: @RoS (CORGRAS)
* Project home: https://corgras.github.io/readmore/
* Github: https://github.com/corgras/readmore.js
* Licensed under the MIT license
*/
!function(e,t){"function"==typeof define&&define.amd?define([],t):"undefined"!=typeof exports?module.exports=t():e.initReadMore=t()}("undefined"!=typeof self?self:this,(function(){"use strict";return function(e,t={}){const o=Object.assign({},{collapsedHeight:250,speed:300,moreLink:"<span>Read More</span>",lessLink:"<span>Close</span>",breakpoints:{},hideButtonCollapse:!1,disableCollapse:!1,animationMode:"js",animationType:"ease-in-out",scrollToTopOnCollapse:!0,beforeToggle:null,afterToggle:null,blockProcessed:null},t),n=document.querySelectorAll(e);if(!n.length)return void console.error("No elements found for selector:",e);let r;const s=()=>{clearTimeout(r),r=setTimeout((()=>{const e=a(window.innerWidth);n.forEach((t=>i(t,e)))}),100)},a=e=>{const t=o.breakpoints,n=Object.keys(t).map(Number).filter((e=>!isNaN(e))).sort(((e,t)=>e-t));if(!n.length)return o;if(e>n[n.length-1])return null;let r=null;for(const t of n)if(e<=t){r=t;break}return null===r&&(r=n[0]),Object.assign({},o,t[r])},i=(e,t)=>{if(e.dataset.readmoreProcessed&&p(e),!t||t.disableCollapse)return e.style.height="auto",e.removeAttribute("aria-hidden"),void p(e);const o=e.innerHTML.trim();if(!o||/^(?:<p>(?:\s*|<br\s*\/?>)<\/p>|<br\s*\/?>|\s+)$/i.test(o))return e.style.height="auto",void e.removeAttribute("aria-hidden");const n=e.scrollHeight,r=Math.min(t.collapsedHeight,n),s=n>r,a=l(t,s),i=a.querySelector(".cs_readmore-btn");if(d(e,r,t),!s)return e.style.height="auto",e.removeAttribute("aria-hidden"),void(a.style.display="none");e.nextElementSibling?.classList?.contains("cs_readmore-btn-wrapper")||e.after(a),m(e,i,t,r),e.dataset.readmoreProcessed="true",e.setAttribute("aria-expanded","false"),t.blockProcessed?.(e,s)},l=(e,t)=>{const o=document.createElement("div");o.className="cs_readmore-btn-wrapper";const n=document.createElement("button");return n.innerHTML=u(e.moreLink),n.className="cs_readmore-btn",n.type="button",n.setAttribute("aria-expanded","false"),n.setAttribute("aria-controls",`readmore-${Math.random().toString(36).slice(2,11)}`),n.dataset.readmoreBtnToggle="collapsed",o.appendChild(n),t||(o.style.display="none"),o},d=(e,t,o)=>{Object.assign(e.style,{overflow:"hidden",height:`${t}px`,transition:"js"===o.animationMode?`height ${o.speed}ms ${o.animationType}`:""}),e.dataset.readmoreBlockToggle="collapsed",e.setAttribute("role","area"),"css"===o.animationMode&&e.classList.add("cs_readmore-animation")},c=(e,t)=>{const o=window.scrollY,n=e.getBoundingClientRect().top+o,r=performance.now(),s=e=>{const a=e-r,i=Math.min(a/t,1),l=i*(2-i);window.scrollTo(0,o+(n-o)*l),i<1&&requestAnimationFrame(s)};requestAnimationFrame(s)},m=(e,t,o,n)=>{let r=!1;t.addEventListener("click",(s=>{s.preventDefault(),r=!r,o.beforeToggle?.(t,e,r),e.dispatchEvent(new CustomEvent("readmore:beforeToggle"));const a=(()=>{const t=e.cloneNode(!0);Object.assign(t.style,{height:"auto",position:"absolute",visibility:"hidden"}),document.body.appendChild(t);const o=t.scrollHeight;return document.body.removeChild(t),o})();if("css"===o.animationMode)r?(e.style.height=`${a}px`,e.classList.add("cs_readmore-expanded"),setTimeout((()=>{e.style.height="auto",e.removeAttribute("aria-hidden")}),o.speed)):(e.style.height=`${e.scrollHeight}px`,e.classList.remove("cs_readmore-expanded"),setTimeout((()=>{e.style.height=`${n}px`,e.setAttribute("aria-hidden","true")}),0),o.scrollToTopOnCollapse&&c(e,200));else{const t=r?o.speed:o.speed/2;e.style.transition=`height ${t}ms ${o.animationType}`,e.style.height=r?`${a}px`:`${n}px`,setTimeout((()=>{r?(e.style.height="auto",e.removeAttribute("aria-hidden")):(e.setAttribute("aria-hidden","true"),o.scrollToTopOnCollapse&&c(e,200))}),t)}t.innerHTML=u(r?o.lessLink:o.moreLink),e.dataset.readmoreBlockToggle=r?"expanded":"collapsed",t.dataset.readmoreBtnToggle=r?"expanded":"collapsed";const i=r.toString();e.setAttribute("aria-expanded",i),t.setAttribute("aria-expanded",i),t.parentElement.style.display=r&&o.hideButtonCollapse?"none":"block",o.afterToggle?.(t,e,r),e.dispatchEvent(new CustomEvent("readmore:afterToggle"))}))},p=e=>{const t=e.nextElementSibling;t?.classList.contains("cs_readmore-btn-wrapper")&&t.remove(),e.style.cssText="",e.classList.remove("cs_readmore-animation","cs_readmore-expanded"),["aria-expanded","aria-hidden","role"].forEach((t=>e.removeAttribute(t))),delete e.dataset.readmoreProcessed,delete e.dataset.readmoreBlockToggle},u=e=>{try{const t=document.createElement("div");return t.innerHTML=e,t.innerHTML.replace(/on\w+="[^"]*"/g,"").replace(/javascript:/g,"")}catch(t){return console.error("Error sanitizing HTML:",t),e}},h=a(window.innerWidth);return h&&!h.disableCollapse&&n.forEach((e=>i(e,h))),window.addEventListener("resize",s),{destroy:()=>{window.removeEventListener("resize",s),n.forEach(p)}}}}));
//# sourceMappingURL=readmore.min.js.map