Merge "Vector: Fix padding values of div#content"
[lhc/web/wiklou.git] / resources / jquery / jquery.autoEllipsis.js
1 /**
2 * Plugin that automatically truncates the plain text contents of an element
3 * and adds an ellipsis.
4 */
5 ( function ( $ ) {
6
7 var
8 // Cache ellipsed substrings for every string-width-position combination
9 cache = {},
10
11 // Use a separate cache when match highlighting is enabled
12 matchTextCache = {};
13
14 $.fn.autoEllipsis = function ( options ) {
15 options = $.extend( {
16 position: 'center',
17 tooltip: false,
18 restoreText: false,
19 hasSpan: false,
20 matchText: null
21 }, options );
22
23 return this.each( function () {
24 var $trimmableText,
25 text, trimmableText, w, pw,
26 l, r, i, side, m,
27 // container element - used for measuring against
28 $container = $(this);
29
30 if ( options.restoreText ) {
31 if ( !$container.data( 'autoEllipsis.originalText' ) ) {
32 $container.data( 'autoEllipsis.originalText', $container.text() );
33 } else {
34 $container.text( $container.data( 'autoEllipsis.originalText' ) );
35 }
36 }
37
38 // trimmable text element - only the text within this element will be trimmed
39 if ( options.hasSpan ) {
40 $trimmableText = $container.children( options.selector );
41 } else {
42 $trimmableText = $( '<span>' )
43 .css( 'whiteSpace', 'nowrap' )
44 .text( $container.text() );
45 $container
46 .empty()
47 .append( $trimmableText );
48 }
49
50 text = $container.text();
51 trimmableText = $trimmableText.text();
52 w = $container.width();
53 pw = 0;
54
55 // Try cache
56 if ( options.matchText ) {
57 if ( !( text in matchTextCache ) ) {
58 matchTextCache[text] = {};
59 }
60 if ( !( options.matchText in matchTextCache[text] ) ) {
61 matchTextCache[text][options.matchText] = {};
62 }
63 if ( !( w in matchTextCache[text][options.matchText] ) ) {
64 matchTextCache[text][options.matchText][w] = {};
65 }
66 if ( options.position in matchTextCache[text][options.matchText][w] ) {
67 $container.html( matchTextCache[text][options.matchText][w][options.position] );
68 if ( options.tooltip ) {
69 $container.attr( 'title', text );
70 }
71 return;
72 }
73 } else {
74 if ( !( text in cache ) ) {
75 cache[text] = {};
76 }
77 if ( !( w in cache[text] ) ) {
78 cache[text][w] = {};
79 }
80 if ( options.position in cache[text][w] ) {
81 $container.html( cache[text][w][options.position] );
82 if ( options.tooltip ) {
83 $container.attr( 'title', text );
84 }
85 return;
86 }
87 }
88
89 if ( $trimmableText.width() + pw > w ) {
90 switch ( options.position ) {
91 case 'right':
92 // Use binary search-like technique for efficiency
93 l = 0;
94 r = trimmableText.length;
95 do {
96 m = Math.ceil( ( l + r ) / 2 );
97 $trimmableText.text( trimmableText.substr( 0, m ) + '...' );
98 if ( $trimmableText.width() + pw > w ) {
99 // Text is too long
100 r = m - 1;
101 } else {
102 l = m;
103 }
104 } while ( l < r );
105 $trimmableText.text( trimmableText.substr( 0, l ) + '...' );
106 break;
107 case 'center':
108 // TODO: Use binary search like for 'right'
109 i = [Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 )];
110 // Begin with making the end shorter
111 side = 1;
112 while ( $trimmableText.outerWidth() + pw > w && i[0] > 0 ) {
113 $trimmableText.text( trimmableText.substr( 0, i[0] ) + '...' + trimmableText.substr( i[1] ) );
114 // Alternate between trimming the end and begining
115 if ( side === 0 ) {
116 // Make the begining shorter
117 i[0]--;
118 side = 1;
119 } else {
120 // Make the end shorter
121 i[1]++;
122 side = 0;
123 }
124 }
125 break;
126 case 'left':
127 // TODO: Use binary search like for 'right'
128 r = 0;
129 while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
130 $trimmableText.text( '...' + trimmableText.substr( r ) );
131 r++;
132 }
133 break;
134 }
135 }
136 if ( options.tooltip ) {
137 $container.attr( 'title', text );
138 }
139 if ( options.matchText ) {
140 $container.highlightText( options.matchText );
141 matchTextCache[text][options.matchText][w][options.position] = $container.html();
142 } else {
143 cache[text][w][options.position] = $container.html();
144 }
145
146 } );
147 };
148
149 }( jQuery ) );