Created
March 18, 2018 12:09
-
-
Save anonymous/a167d901346c1bdebbcd88e91b495914 to your computer and use it in GitHub Desktop.
Middle ellipsis (source: https://jsfiddle.net/Sjeiti/cxsqv50n/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<main> | |
<h1 data-middle-ellipsis>A Javascript solution to middle ellipsis</h1> | |
<div data-middle-ellipsis>The quick fox</div> | |
<div data-middle-ellipsis class="inline-block">The lazy dog</div> | |
<div data-middle-ellipsis>theQuickBrownFoxJumpsOverTheLazyDog</div> | |
<div data-middle-ellipsis class="bold">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis class="small">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis class="small bold">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis class="large">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis>The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="70">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="30">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="1">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="99">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="-3">The quick brown fox jumps over the lazy dog</div> | |
<div data-middle-ellipsis="-3">The quick brown dog</div> | |
<div data-middle-ellipsis="0">The quick brown dog</div> | |
<div data-middle-ellipsis="-1">The quick brown dog</div> | |
<div data-middle-ellipsis="-99">The quick brown dog</div> | |
</main> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Attibute modifier to create middle ellipsis | |
* When the attribute value is left blank the ellipsis will be in the middle | |
* When positive the attribute value will be used as a percentage | |
* When negative the attribute value will be used as character index counted from the end | |
* @example | |
* <div data-middle-ellipsis>A Javascript solution to middle ellipsis</div> | |
* <div data-middle-ellipsis="20">A Javascript solution to middle ellipsis</div> | |
* <div data-middle-ellipsis="-3">A Javascript solution to middle ellipsis</div> | |
*/ | |
const attributeName = 'data-middle-ellipsis' | |
const attributeTextName = attributeName+'-text' | |
const attributeFontName = attributeName+'-font' | |
const clamp = (val,min=Number.NEGATIVE_INFINITY,max=Number.POSITIVE_INFINITY)=>Math.max(min,Math.min(max,val)) | |
const ellipsis = '…' | |
const map = new Map() | |
let timeoutId | |
testMiddleEllipsis() | |
window.addEventListener('resize', onResize, { capture: true, passive: true }) | |
function onResize(e){ | |
clearTimeout(timeoutId) | |
timeoutId = setTimeout(testMiddleEllipsis, 200) | |
} | |
function testMiddleEllipsis() { | |
Array.from(document.querySelectorAll(`[${attributeName}]`)).forEach(elm=>{ | |
// do not recalculate variables a second time | |
const mapped = map.get(elm) | |
let {text, textLength, from, multiplier, font, textWidth, elementWidth} = mapped||{} | |
// first time | |
if (!mapped) { | |
text = elm.textContent | |
textLength = text.length | |
from = parseFloat(elm.getAttribute(attributeName))||50 | |
multiplier = from>0&&from/100 | |
const computedStyle = window.getComputedStyle(elm, null) | |
font = `${computedStyle.getPropertyValue('font-weight')} ${computedStyle.getPropertyValue('font-size')} ${computedStyle.getPropertyValue('font-family')}` | |
textWidth = getTextWidth(text, font) | |
elementWidth = elm.offsetWidth | |
map.set(elm, {text, textLength, from, multiplier, font, textWidth, elementWidth}) | |
} | |
// | |
const {offsetWidth} = elm | |
const widthChanged = !mapped||elementWidth!==offsetWidth | |
mapped&&widthChanged&&(mapped.elementWidth=elementWidth=offsetWidth) | |
// | |
if (widthChanged&&textWidth>elementWidth) { | |
elm.setAttribute('title', text) | |
let smallerText = text | |
let smallerWidth = elementWidth | |
while(smallerText.length>3){ | |
let smallerTextLength = smallerText.length | |
const half = multiplier&& | |
clamp(multiplier*smallerTextLength<<0,1,smallerTextLength-2)|| | |
Math.max(smallerTextLength+from-1,1) | |
const half1 = smallerText.substr(0,half).replace(/\s*$/,'') | |
const half2 = smallerText.substr(half+1).replace(/^\s*/,'') | |
smallerText = half1+half2 | |
smallerWidth = getTextWidth(smallerText+ellipsis, font) | |
if (smallerWidth<elementWidth) { | |
elm.textContent = half1+ellipsis+half2 | |
break; | |
} | |
} | |
} | |
}) | |
} | |
/** | |
* Get the text width | |
* @param {string} text | |
* @param {string} font | |
*/ | |
function getTextWidth(text, font) { | |
let context = getTextWidth.context | |
if (!context) { | |
const canvas = document.createElement('canvas') | |
context = getTextWidth.context = canvas.getContext('2d') | |
} | |
context.font = font | |
const metrics = context.measureText(text) | |
return metrics.width | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$width: 130px; | |
html,body{ | |
width: 100%; | |
height: 100%; | |
line-height: 170%; | |
} | |
main { | |
width: 100%; | |
height: 100%; | |
font-family: Arial; | |
background: #fff linear-gradient(90deg | |
,transparent $width | |
,#f0f0f0 $width | |
,#f0f0f0 2*$width | |
,transparent 2*$width | |
); | |
} | |
[data-middle-ellipsis]{ | |
max-width: $width; | |
white-space: nowrap; | |
box-shadow: -1px 0 0 red inset; | |
} | |
.inline-block { display: inline-block; } | |
.bold { font-weight: bold; } | |
.small { font-size: 10px; } | |
.large { font-size: 32px; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment