Skip to content

Instantly share code, notes, and snippets.

@fhrbek
Last active June 14, 2016 10:49
Show Gist options
  • Save fhrbek/1e9ebd5c407a5ee300ffe94fe53aea66 to your computer and use it in GitHub Desktop.
Save fhrbek/1e9ebd5c407a5ee300ffe94fe53aea66 to your computer and use it in GitHub Desktop.
Truncation
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
textSamples: [
[
'This is quite a long text',
'A short text',
'MMMMMMMMMMMMMMIIIIIIIIIIIIIII',
'jjjjjjjjjjjjjjOOOOOOOOOOOOOOO',
]
],
init: function () {
let textSamples = this.get('textSamples');
for (let sampleIndex=1; sampleIndex <= 3; sampleIndex++) {
textSamples[sampleIndex] = [];
for (let i=0; i < Math.pow(10, sampleIndex); i++) {
textSamples[sampleIndex][i] = 'Text ' + i + ' is toooooooooooooooooooooooooooooooo long to be displayed';
}
}
},
sampleIndex: 0,
texts: Ember.computed('sampleIndex', function () {
return this.get('textSamples')[this.get('sampleIndex')];
}),
itemCount: Ember.computed('textSamples', 'sampleIndex', function () {
return this.get('textSamples')[this.get('sampleIndex')].length;
}),
actions: {
toggleSamples: function () {
let newIndex = this.get('sampleIndex') + 1;
this.set('sampleIndex', newIndex < this.get('textSamples').length ? newIndex : 0);
}
}
});
import Ember from 'ember';
export default Ember.Component.extend({
headCount: 0,
headValue: Ember.computed('value', 'headCount', function () {
return this.get('value').substr(0, this.get('headCount'));
}),
ellipsisValue: Ember.computed('ellipsisApplied', function () {
return this.get('ellipsisApplied') ? Ember.String.htmlSafe('&hellip;') : '';
}),
tailCount: 0,
tailValue: Ember.computed('value', 'tailCount', 'ellipsisApplied', function () {
return this.get('value').substr(-this.get('tailCount'), this.get('tailCount'));
}),
ellipsisApplied: false,
lastValue: '',
titleValue: Ember.computed('value', 'ellipsisApplied', function() {
return this.get('ellipsisApplied') ? this.get('value') : '';
}),
hide: function () {
this.$().css('visibility', 'hidden');
},
show: function () {
this.$().css('visibility', '');
},
didInsertElement: function () {
this.hide(); // hide on insertion
},
willUpdate: function () {
this.hide(); // hide on update
},
adjusting: false,
try: function () {
let boxWidth = this.$().width(),
textWidth = this.$('.me-full-measure').width(),
needsEllipsis = textWidth > boxWidth;
if (needsEllipsis != this.get('ellipsisApplied') || this.get('lastValue') !== this.get('value')) {
this.set('lastValue', this.get('value'));
Ember.run.next(() => {
this.set('ellipsisApplied', needsEllipsis);
if (needsEllipsis) {
this.adjust();
} else {
this.show();
}
});
} else {
this.show();
}
},
adjust: function () {
let len = this.get('value').length,
initCount = Math.floor(len/4);
this.set('adjusting', true);
this.setProperties({
headCount: initCount,
tailCount: initCount,
lastHeadCount: 0,
lastTailCount: 0
});
},
finishAdjustment: function () {
Ember.run.next(() => {
let boxWidth = this.$().width(),
headWidth = this.$('.me-head').width(),
tailWidth = this.$('.me-tail').width(),
ellipsisWidth = this.$('.me-ellipsis').width(),
maxFragmentWidth = (boxWidth - ellipsisWidth) / 2,
headCurr = this.get('headCount'),
headLast = this.get('lastHeadCount'),
headDiff = headCurr - headLast,
headShift = Math.floor(Math.abs(headDiff) / 2),
tailCurr = this.get('tailCount'),
tailLast = this.get('lastTailCount'),
tailDiff = tailCurr - tailLast,
tailShift = Math.floor(Math.abs(tailDiff) / 2);
if (headShift === 0) {
headShift = 1;
}
if (tailShift === 0) {
tailShift = 1;
}
if (headDiff !== 0 && headWidth < maxFragmentWidth) {
this.setProperties({
lastHeadCount: headCurr,
headCount: headCurr + headShift
});
} else if (headWidth > maxFragmentWidth) {
if (headDiff !== 1 && headCurr >= headShift) {
this.setProperties({
lastHeadCount: headCurr,
headCount: headCurr - headShift
});
} else {
this.set('headCount', headLast);
headShift = 0; // finalize head
}
} else {
headShift = 0; // finalize head
}
if (tailDiff !== 0 && tailWidth < maxFragmentWidth) {
this.setProperties({
lastTailCount: tailCurr,
tailCount: tailCurr + tailShift
});
} else if (tailWidth > maxFragmentWidth) {
if (tailDiff !== 1 && tailCurr >= tailShift) {
this.setProperties({
lastTailCount: tailCurr,
tailCount: tailCurr - tailShift
});
} else {
this.set('tailCount', tailLast);
tailShift = 0; // finalize tail
}
} else {
tailShift = 0; // finalize tail
}
if (headShift === 0 && tailShift === 0) {
this.set('adjusting', false);
this.show();
}
});
},
didRender: function () {
if (this.get('adjusting')) {
this.finishAdjustment();
} else {
this.try();
}
}
});
<div class="me-wrapper">
<span class="me-full-measure">{{value}}</span>
{{#unless ellipsisApplied}}
<span class="me-full">{{value}}</span>
{{else}}
<div class="me-truncated" title={{titleValue}} aria-label={{value}}>
<span class="me-head">{{headValue}}</span>
<span class="me-ellipsis">{{ellipsisValue}}</span>
<span class="me-tail">{{tailValue}}</span>
</div>
{{/unless}}
</div>
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.content {
width: 150px;
white-space: nowrap;
overflow: hidden;
border: 1px solid black;
}
.me-wrapper {
position: relative;
}
.me-full-measure {
visibility: hidden;
}
.me-full,
.me-truncated {
position: absolute;
top: 0;
left: 0;
}
.me-head,
.me-ellipsis,
.me-tail {
float: left;
}
<h1>Welcome to {{appName}}</h1>
<br>
<br>
{{outlet}}
<button {{action "toggleSamples"}}>Toggle Samples</button>
<hr/>
Displaying {{itemCount}} items
<hr/>
<div class="content">
{{~#each texts as |text|~}}
{{~middle-ellipsis value=text~}}
{{~/each~}}
</div>
<br>
<br>
{
"version": "0.8.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": true,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.5.1",
"ember-data": "2.5.2",
"ember-template-compiler": "2.5.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment