forked from adobe/balance-text
-
Notifications
You must be signed in to change notification settings - Fork 0
/
balancetext.min.js
1 lines (1 loc) · 8.91 KB
/
balancetext.min.js
1
"use strict";(function(root,factory){if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory()}else{root.balanceText=factory()}})(this,function(){var breakMatches,wsnwMatches,wsnwOffset;var watching={sel:[],el:[]};var handlersInitialized=false;var polyfilled=false;function noop(){return}function forEach(elements,callback){Array.prototype.forEach.call(elements,callback)}function ready(fn){if(document.readyState!=="loading"){fn()}else if(document.addEventListener){document.addEventListener("DOMContentLoaded",fn)}else{document.attachEvent("onreadystatechange",function(){if(document.readyState!=="loading"){fn()}})}}function debounce(func,threshold,execAsap){var timeout;return function debounced(){var obj=this,args=arguments;function delayed(){if(!execAsap){func.apply(obj,args)}timeout=null}if(timeout){clearTimeout(timeout)}else if(execAsap){func.apply(obj,args)}timeout=setTimeout(delayed,threshold||100)}}function hasTextWrap(){var style=document.documentElement.style;return style.textWrap||style.WebkitTextWrap||style.MozTextWrap||style.MsTextWrap}function NextWS_params(){this.reset()}NextWS_params.prototype.reset=function(){this.index=0;this.width=0};function isWhiteSpaceNoWrap(index){return wsnwMatches.some(function(range){return range.start<index&&index<range.end})}function recursiveCalcNoWrapOffsetsForLine(el,includeTag){if(el.nodeType===el.ELEMENT_NODE){var style=window.getComputedStyle(el);if(style.whiteSpace==="nowrap"){var len=el.outerHTML.length;wsnwMatches.push({start:wsnwOffset,end:wsnwOffset+len});wsnwOffset+=len}else{forEach(el.childNodes,function(child){recursiveCalcNoWrapOffsetsForLine(child,true)});if(includeTag){wsnwOffset+=el.outerHTML.length-el.innerHTML.length}}}else if(el.nodeType===el.COMMENT_NODE){wsnwOffset+=el.length+7}else if(el.nodeType===el.PROCESSING_INSTRUCTION_NODE){wsnwOffset+=el.length+2}else{wsnwOffset+=el.length}}function calcNoWrapOffsetsForLine(el,oldWS,lineCharOffset){if(lineCharOffset===0){el.style.whiteSpace=oldWS;wsnwOffset=0;wsnwMatches=[];recursiveCalcNoWrapOffsetsForLine(el,false);el.style.whiteSpace="nowrap"}else{var newMatches=[];wsnwMatches.forEach(function(match){if(match.start>lineCharOffset){newMatches.push({start:match.start-lineCharOffset,end:match.end-lineCharOffset})}});wsnwMatches=newMatches}}function removeTags(el){var brs=el.querySelectorAll('br[data-owner="balance-text-hyphen"]');forEach(brs,function(br){br.outerHTML=""});brs=el.querySelectorAll('br[data-owner="balance-text"]');forEach(brs,function(br){br.outerHTML=" "});var spans=el.querySelectorAll('span[data-owner="balance-text-softhyphen"]');if(spans.length>0){forEach(spans,function(span){var textNode=document.createTextNode("");span.parentNode.insertBefore(textNode,span);span.parentNode.removeChild(span)})}spans=el.querySelectorAll('span[data-owner="balance-text-justify"]');if(spans.length>0){var txt="";forEach(spans,function(span){txt+=span.textContent;span.parentNode.removeChild(span)});el.innerHTML=txt}}var isJustified=function(el){var style=el.currentStyle||window.getComputedStyle(el,null);return style.textAlign==="justify"};function justify(el,txt,conWidth){var div,size,tmp,words,wordSpacing;txt=txt.trim();words=txt.split(" ").length;txt=txt+" ";if(words<2){return txt}tmp=document.createElement("span");tmp.innerHTML=txt;el.appendChild(tmp);size=tmp.offsetWidth;tmp.parentNode.removeChild(tmp);wordSpacing=Math.floor((conWidth-size)/(words-1));tmp.style.wordSpacing=wordSpacing+"px";tmp.setAttribute("data-owner","balance-text-justify");div=document.createElement("div");div.appendChild(tmp);return div.innerHTML}function isBreakChar(txt,index){var re=/([^\S\u00a0]|-|\u2014|\u2013|\u00ad)(?![^<]*>)/g,match;if(!breakMatches){breakMatches=[];match=re.exec(txt);while(match!==null){if(!isWhiteSpaceNoWrap(match.index)){breakMatches.push(match.index)}match=re.exec(txt)}}return breakMatches.indexOf(index)!==-1}function isBreakOpportunity(txt,index){return index===0||index===txt.length||isBreakChar(txt,index-1)&&!isBreakChar(txt,index)}function findBreakOpportunity(el,txt,conWidth,desWidth,dir,c,ret){var w;if(txt&&typeof txt==="string"){for(;;){while(!isBreakOpportunity(txt,c)){c+=dir}el.innerHTML=txt.substr(0,c);w=el.offsetWidth;if(dir<0){if(w<=desWidth||w<=0||c===0){break}}else{if(desWidth<=w||conWidth<=w||c===txt.length){break}}c+=dir}}ret.index=c;ret.width=w}function getSpaceWidth(el,h){var dims,space,spaceRatio,container=document.createElement("div");container.style.display="block";container.style.position="absolute";container.style.bottom=0;container.style.right=0;container.style.width=0;container.style.height=0;container.style.margin=0;container.style.padding=0;container.style.visibility="hidden";container.style.overflow="hidden";space=document.createElement("span");space.style.fontSize="2000px";space.innerHTML=" ";container.appendChild(space);el.appendChild(container);dims=space.getBoundingClientRect();container.parentNode.removeChild(container);spaceRatio=dims.height/dims.width;return h/spaceRatio}function getElementsList(elements){if(!elements){return[]}if(typeof elements==="string"){return document.querySelectorAll(elements)}if(elements.tagName&&elements.querySelectorAll){return[elements]}return elements}function balanceText(elements){forEach(getElementsList(elements),function(el){var maxTextWidth=5e3;removeTags(el);var oldWS=el.style.whiteSpace,oldFloat=el.style.float,oldDisplay=el.style.display,oldPosition=el.style.position,oldLH=el.style.lineHeight;el.style.lineHeight="normal";var containerWidth=el.offsetWidth,containerHeight=el.offsetHeight;el.style.whiteSpace="nowrap";el.style.float="none";el.style.display="inline";el.style.position="static";var nowrapWidth=el.offsetWidth,nowrapHeight=el.offsetHeight,spaceWidth=oldWS==="pre-wrap"?0:getSpaceWidth(el,nowrapHeight);if(containerWidth>0&&nowrapWidth>containerWidth&&nowrapWidth<maxTextWidth){var remainingText=el.innerHTML,newText="",lineText="",shouldJustify=isJustified(el),totLines=Math.round(containerHeight/nowrapHeight),remLines=totLines,lineCharOffset=0;var desiredWidth,guessIndex,le,ge,splitIndex,isHyphen,isSoftHyphen;while(remLines>1){breakMatches=null;calcNoWrapOffsetsForLine(el,oldWS,lineCharOffset);desiredWidth=Math.round((nowrapWidth+spaceWidth)/remLines-spaceWidth);guessIndex=Math.round((remainingText.length+1)/remLines)-1;le=new NextWS_params;findBreakOpportunity(el,remainingText,containerWidth,desiredWidth,-1,guessIndex,le);ge=new NextWS_params;guessIndex=le.index;findBreakOpportunity(el,remainingText,containerWidth,desiredWidth,+1,guessIndex,ge);le.reset();guessIndex=ge.index;findBreakOpportunity(el,remainingText,containerWidth,desiredWidth,-1,guessIndex,le);if(le.index===0){splitIndex=ge.index}else if(containerWidth<ge.width||le.index===ge.index){splitIndex=le.index}else{splitIndex=Math.abs(desiredWidth-le.width)<Math.abs(ge.width-desiredWidth)?le.index:ge.index}lineText=remainingText.substr(0,splitIndex).replace(/\s$/,"");isSoftHyphen=Boolean(lineText.match(/\u00ad$/));if(isSoftHyphen){lineText=lineText.replace(/\u00ad$/,'<span data-owner="balance-text-softhyphen">-</span>')}if(shouldJustify){newText+=justify(el,lineText,containerWidth)}else{newText+=lineText;isHyphen=isSoftHyphen||Boolean(lineText.match(/(-|\u2014|\u2013)$/));newText+=isHyphen?'<br data-owner="balance-text-hyphen" />':'<br data-owner="balance-text" />'}remainingText=remainingText.substr(splitIndex);lineCharOffset=splitIndex;remLines--;el.innerHTML=remainingText;nowrapWidth=el.offsetWidth}if(shouldJustify){el.innerHTML=newText+justify(el,remainingText,containerWidth)}else{el.innerHTML=newText+remainingText}}el.style.whiteSpace=oldWS;el.style.float=oldFloat;el.style.display=oldDisplay;el.style.position=oldPosition;el.style.lineHeight=oldLH})}function updateWatched(){var selectors=watching.sel.join(","),selectedElements=getElementsList(selectors),elements=Array.prototype.concat.apply(watching.el,selectedElements);balanceText(elements)}function initHandlers(){if(handlersInitialized){return}ready(updateWatched);window.addEventListener("load",updateWatched);window.addEventListener("resize",debounce(updateWatched));handlersInitialized=true}function balanceTextAndWatch(elements){if(typeof elements==="string"){watching.sel.push(elements)}else{forEach(getElementsList(elements),function(el){watching.el.push(el)})}initHandlers();updateWatched()}function unwatch(elements){if(typeof elements==="string"){watching.sel=watching.sel.filter(function(el){return el!==elements})}else{elements=getElementsList(elements);watching.el=watching.el.filter(function(el){return elements.indexOf(el)===-1})}}function polyfill(){if(polyfilled){return}watching.sel.push(".balance-text");initHandlers();polyfilled=true}function publicInterface(elements,options){if(!elements){polyfill()}else if(options&&options.watch===true){balanceTextAndWatch(elements)}else if(options&&options.watch===false){unwatch(elements)}else{balanceText(elements)}}publicInterface.updateWatched=updateWatched;if(hasTextWrap()){noop.updateWatched=noop;return noop}return publicInterface});