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