Browse Source

Fix middle ellipsis cut on resize

master
Eduard Kuzmenko 4 years ago
parent
commit
6d62a9a660
  1. 62
      src/components/middleEllipsis.ts
  2. 6
      src/components/wrappers.ts

62
src/components/middleEllipsis.ts

@ -11,7 +11,6 @@ import { clamp } from "../helpers/number";
* <div data-middle-ellipsis="20">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> * <div data-middle-ellipsis="-3">A Javascript solution to middle ellipsis</div>
*/ */
const attributeName = 'data-middle-ellipsis';
const ellipsis = '…'; const ellipsis = '…';
const map: Map<HTMLElement, { const map: Map<HTMLElement, {
text: string, text: string,
@ -39,42 +38,51 @@ const testQueueElements = () => {
}; };
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
(Array.from(document.querySelectorAll(`[${attributeName}]`)) as HTMLElement[]).forEach(el => testQueue.add(el)); for(const [key] of map) {
testQueue.add(key);
}
setTestQueue(); setTestQueue();
}, {capture: true, passive: true}); }, {capture: true, passive: true});
const testElement = (elm: HTMLElement) => { const testElement = (element: HTMLElement) => {
//const perf = performance.now(); //const perf = performance.now();
// do not recalculate variables a second time // do not recalculate variables a second time
const mapped = map.get(elm); let mapped = map.get(element);
const firstTime = !mapped;
let {text, textLength, from, multiplier, font, textWidth, elementWidth} = mapped || {}; let {text, textLength, from, multiplier, font, textWidth, elementWidth} = mapped || {};
// first time //console.log('[MEE] testElement got mapped', mapped);
if(!mapped) {
text = elm.textContent; if(firstTime) {
text = element.textContent;
textLength = text.length; textLength = text.length;
from = parseFloat(elm.getAttribute(attributeName)) || 50; from = /* parseFloat(element.getAttribute(attributeName)) || */50;
multiplier = from > 0 && from / 100; multiplier = from > 0 && from / 100;
//const perf = performance.now(); //const perf = performance.now();
font = `${elm.dataset.fontWeight || 400} ${fontSize} ${fontFamily}`; font = `${element.dataset.fontWeight || 400} ${fontSize} ${fontFamily}`;
/* const computedStyle = window.getComputedStyle(elm, null); /* const computedStyle = window.getComputedStyle(elm, null);
font = `${computedStyle.getPropertyValue('font-weight')} ${computedStyle.getPropertyValue('font-size')} ${computedStyle.getPropertyValue('font-family')}`; */ font = `${computedStyle.getPropertyValue('font-weight')} ${computedStyle.getPropertyValue('font-size')} ${computedStyle.getPropertyValue('font-family')}`; */
//console.log('testMiddleEllipsis get computed style:', performance.now() - perf, font); //console.log('testMiddleEllipsis get computed style:', performance.now() - perf, font);
textWidth = getTextWidth(text, font); textWidth = getTextWidth(text, font);
//const perf = performance.now(); //const perf = performance.now();
elementWidth = elm.offsetWidth; elementWidth = element.getBoundingClientRect().width;
//console.log('testMiddleEllipsis get offsetWidth:', performance.now() - perf, font); //console.log('testMiddleEllipsis get offsetWidth:', performance.now() - perf, font);
map.set(elm, {text, textLength, from, multiplier, font, textWidth, elementWidth}); mapped = {text, textLength, from, multiplier, font, textWidth, elementWidth};
map.set(element, mapped);
//console.log('[MEE] testElement map set', element);
} }
const {offsetWidth} = elm; const newElementWidth = element.getBoundingClientRect().width;
const widthChanged = !mapped || elementWidth !== offsetWidth; const widthChanged = firstTime || elementWidth !== newElementWidth;
mapped && widthChanged && (mapped.elementWidth = elementWidth = offsetWidth); !firstTime && widthChanged && (mapped.elementWidth = elementWidth = newElementWidth);
if(widthChanged) { if(widthChanged) {
if(textWidth > elementWidth) { if(textWidth > elementWidth) {
elm.setAttribute('title', text); element.setAttribute('title', text);
let smallerText = text; let smallerText = text;
let smallerWidth = elementWidth; let smallerWidth = elementWidth;
while(smallerText.length > 3) { while(smallerText.length > 3) {
@ -87,12 +95,16 @@ const testElement = (elm: HTMLElement) => {
smallerText = half1 + half2; smallerText = half1 + half2;
smallerWidth = getTextWidth(smallerText + ellipsis, font); smallerWidth = getTextWidth(smallerText + ellipsis, font);
if(smallerWidth < elementWidth) { if(smallerWidth < elementWidth) {
elm.textContent = half1 + ellipsis + half2; element.textContent = half1 + ellipsis + half2;
break; break;
} }
} }
// * set new width after cutting text
mapped.elementWidth = element.getBoundingClientRect().width;
//mapped.textWidth = smallerWidth;
} else { } else {
elm.removeAttribute('title'); element.removeAttribute('title');
} }
} }
@ -116,27 +128,29 @@ function getTextWidth(text: string, font: string) {
//context.font = font; //context.font = font;
const metrics = context.measureText(text); const metrics = context.measureText(text);
//console.log('getTextWidth perf:', performance.now() - perf); //console.log('getTextWidth perf:', performance.now() - perf);
//return metrics.width; return metrics.width;
return Math.round(metrics.width); //return Math.round(metrics.width);
} }
export class MiddleEllipsisElement extends HTMLElement { export class MiddleEllipsisElement extends HTMLElement {
constructor() { constructor() {
super(); super();
if(this.getAttribute('data-middle-ellipsis') === null) {
this.setAttribute('data-middle-ellipsis', '');
}
} }
connectedCallback() { connectedCallback() {
//console.log('[MEE]: connectedCallback before', map.has(this), testQueue.has(this), map.size, this.textContent, map);
map.set(this, null);
testQueue.add(this); testQueue.add(this);
setTestQueue(); setTestQueue();
//testElement(this); //testElement(this);
//console.log('[MEE]: connectedCallback after', map.has(this), map.size, testQueue.has(this), testQueue.size);
} }
disconnectedCallback() { disconnectedCallback() {
map.delete(this); const deleted = map.delete(this);
//console.log('[MEE]: disconnectedCallback', deleted, map.has(this), map.size, this.textContent, map);
} }
} }

6
src/components/wrappers.ts

@ -26,7 +26,6 @@ import ProgressivePreloader from './preloader';
import './middleEllipsis'; import './middleEllipsis';
import { nextRandomInt } from '../helpers/random'; import { nextRandomInt } from '../helpers/random';
import RichTextProcessor from '../lib/richtextprocessor'; import RichTextProcessor from '../lib/richtextprocessor';
import appImManager from '../lib/appManagers/appImManager';
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
@ -413,7 +412,8 @@ export function wrapDocument(doc: MyDocument, withTime = false, uploading = fals
preloader = new ProgressivePreloader(null, true); preloader = new ProgressivePreloader(null, true);
} }
download = appDocsManager.saveDocFile(doc, appImManager.chat.bubbles.lazyLoadQueue.queueId); preloader.attach(downloadDiv, true);
/* download = appDocsManager.saveDocFile(doc, appImManager.chat.bubbles.lazyLoadQueue.queueId);
preloader.attach(downloadDiv, true, download); preloader.attach(downloadDiv, true, download);
download.then(() => { download.then(() => {
@ -426,7 +426,7 @@ export function wrapDocument(doc: MyDocument, withTime = false, uploading = fals
downloadDiv.classList.remove('downloading'); downloadDiv.classList.remove('downloading');
}); });
downloadDiv.classList.add('downloading'); downloadDiv.classList.add('downloading'); */
} else { } else {
download.cancel(); download.cancel();
} }

Loading…
Cancel
Save