-
Notifications
You must be signed in to change notification settings - Fork 0
/
ellipsis.js
106 lines (106 loc) · 3.54 KB
/
ellipsis.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"use strict";
var assign = require('lodash.assign');
var contentKey = '__ellipsis-original-content';
var canscroll = function (el, tolerance) {
var scrollRoom = 0,
ost = 0, // old scroll top
nst, // new scroll top
origScrolltop;
// Determine if $el can be scrolled by modifying scrollTop and checking if the change has stuck
// Note: browsers have different tolerances.
origScrolltop = el.scrollTop;
el.scrollTop = 0;
el.scrollTop = 1;
nst = el.scrollTop; // new scroll top
while (ost !== nst) {
ost = el.scrollTop;
el.scrollTop = ost + 1;
nst = el.scrollTop;
++scrollRoom;
if (scrollRoom > tolerance) { // break early if we can
break;
}
}
el.scrollTop = origScrolltop; // put it back so nobody suspects nothin'
return scrollRoom > tolerance;
};
module.exports = function (el, config) {
config = config || {};
var _canscroll;
var low = 0;
var high;
var test;
var try_this;
var truncated;
var ellipsis;
var after_ellipsis;
var breakables;
var content;
config = assign({
async: true,
skip_slow_browsers: false,
tolerance: 1, // maximum amount the element can scroll before triggering the truncation
content: false, // if not supplied here, content will be scraped from the element itself using $.fn.html()
ellipsis: " … " // will be concatenated to the end of the content if it is truncated
}, config);
_canscroll = canscroll.bind(null, el, config.tolerance);
content = config.content;
if (false === content) {
content = el[contentKey];
if (undefined === content) {
content = el.innerHTML;
el[content] = content;
} else {
el.innerHTML = content;
}
}
if (!content) {
return;
}
breakables = content.split(/\s/);
if (!_canscroll()) {
return;
}
el.innerHTML = "";
breakables.push(" ");
breakables.push(" ");
low = 0;
high = breakables.length;
while (high > low + 1) { // binary search to find the scrolling point
test = Math.floor((low + high) / 2);
el.innerHTML = breakables.slice(0, test).join(" ") + " ";
if (_canscroll()) {
high = test;
} else {
low = test;
}
}
var last = breakables.slice(0, high - 1).join(' ') + " ";
after_ellipsis = document.createElement('span');
after_ellipsis.style.display = 'none';
after_ellipsis.classList.add('ellipsised-content');
ellipsis = document.createElement('span');
ellipsis.classList.add('ellipsis');
ellipsis.innerHTML = config.ellipsis;
truncated = document.createElement('span');
truncated.classList.add('truncated-content');
truncated.innerHTML = last;
el.innerHTML = '';
el.appendChild(truncated);
el.appendChild(ellipsis);
el.appendChild(after_ellipsis);
try_this = last;
// if the ellipsis has made the element scroll again, back off character by character until it doesnt
while (try_this) {
if (try_this.substr(-1).match(/\s/) && !_canscroll()) { // if we are at a space and cannot scroll
break;
}
try_this = try_this.substr(0, try_this.length - 1);
truncated.innerHTML = try_this;
}
if (try_this.length !== last.length) {
after_ellipsis.innerHTML = last.substr(try_this.length - last.length);
}
after_ellipsis.innerHTML += breakables.slice(high - 1).join(" ");
el.innerHTML = el.innerHTML.trim();
}