-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathjquery.textutils.js
More file actions
142 lines (123 loc) · 4.33 KB
/
jquery.textutils.js
File metadata and controls
142 lines (123 loc) · 4.33 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* Tools for working with text
* (c) 2010 Interactive Things
*
* textWidth - measure text width
* shortenText - shorten text using an ellipsis
*
* Note: because of performance improvements, the plugin may
* behave unexpectedly when used on elements with different
* font styles.
*/
(function($) {
// Test Div
var div;
/* TEXT METRICS
/////////////////////////////////////////////////////////////////*/
$.fn.textWidth = function() {
var el = this;
var h = 0, w = 0;
if (!div) {
div = $('<div></div>');
$("body").append(div);
div.css({
position: 'absolute',
left: -1000,
top: -1000,
display: 'none'
});
var styles = ['margin-top', 'margin-right', 'margin-bottom', 'margin-left',
'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width',
'font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing'];
var stylesHash = {};
for (var i=0,l=styles.length;i<l;i++) {
stylesHash[styles[i]] = $(el).css(styles[i]);
}
div.css(stylesHash);
}
div.html($(el).html());
return div.outerWidth();
}
/* SHORTEN TEXT
/////////////////////////////////////////////////////////////////*/
$.fn.fitText = function(targetWidth) {
var charWidth, stack = [];
// Create cache slots that less exact than 1px
var targetWidthSlot = Math.floor(targetWidth/15)*15;
// Use a wide character like the "W" to approximate character width
var first = $(this[0]);
var firstText = first.text();
charWidth = first.text("s").textWidth();
first.text(firstText);
// Fit text for each element
this.each(function() {
var self = this, text, shortenedText, textWidth, counter;
// Make this operation non-blocking.
stack.push(function() {
// Cache the shortened text corresponding to a targetWidth
if (!$(self).data('textCache')) {
$(self).data('textCache', {});
} else {
var cache = $(self).data('textCache');
// If the text has already been calculated, exit
if (cache[targetWidthSlot]) {
$(self).text(cache[targetWidthSlot]);
return;
}
}
// Save the original text
if (!$(self).data('originalText')) {
text = $(self).text();
$(self).data('originalText', text);
} else {
text = $(self).data('originalText');
$(self).text(text);
}
if (!$(self).data('textWidthCache')) {
$(self).data('textWidthCache', {});
textWidth = $(self).textWidth();
} else {
var cache = $(self).data('textWidthCache');
if (cache[targetWidthSlot]) {
textWidth = cache[targetWidthSlot];
} else {
textWidth = $(self).textWidth();
cache[targetWidthSlot] = textWidth;
$(self).data('textWidthCache', cache);
}
}
var hiddenChars = Math.floor((textWidth - targetWidth)/charWidth);
if (hiddenChars < 0) return self;
// Start with deleting the approximated hidden characters
counter = hiddenChars;
while (textWidth > targetWidth) {
if (text.length < 5) {
shortenedText = text.substr(0,leftBoundary) + "…";
$(self).text(shortenedText);
break;
} else {
var newLength = Math.floor(text.length - counter);
var leftBoundary = Math.floor(newLength * 0.7);
var rightBoundary = Math.ceil(text.length - newLength * 0.3);
shortenedText = text.substr(0,leftBoundary) + "…" + text.substr(rightBoundary, text.length);
$(self).text(shortenedText);
}
textWidth = $(self).textWidth();
counter++;
}
var cache = $(self).data('textCache');
cache[targetWidthSlot] = shortenedText;
$(self).data('textCache', cache);
});
});
// Work through stack
setTimeout(stackWorker, 0);
function stackWorker() {
if (stack.length > 0) {
stack.shift().call();
}
setTimeout(stackWorker, 0);
}
}
})(jQuery);