2 * @class jQuery.plugin.autoEllipsis
7 // Cache ellipsed substrings for every string-width-position combination
10 // Use a separate cache when match highlighting is enabled
13 // Due to <https://github.com/jscs-dev/jscs-jsdoc/issues/136>
16 * Automatically truncate the plain text contents of an element and add an ellipsis
18 * @param {Object} options
19 * @param {'left'|'center'|'right'} [options.position='center'] Where to remove text.
20 * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
22 * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
24 * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
25 * or if the library should create a new container for it.
26 * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
30 $.fn
.autoEllipsis = function ( options
) {
39 return this.each( function () {
41 text
, trimmableText
, w
, pw
,
43 // container element - used for measuring against
44 $container
= $( this );
46 if ( options
.restoreText
) {
47 if ( !$container
.data( 'autoEllipsis.originalText' ) ) {
48 $container
.data( 'autoEllipsis.originalText', $container
.text() );
50 $container
.text( $container
.data( 'autoEllipsis.originalText' ) );
54 // trimmable text element - only the text within this element will be trimmed
55 if ( options
.hasSpan
) {
56 $trimmableText
= $container
.children( options
.selector
);
58 $trimmableText
= $( '<span>' )
59 .css( 'whiteSpace', 'nowrap' )
60 .text( $container
.text() );
63 .append( $trimmableText
);
66 text
= $container
.text();
67 trimmableText
= $trimmableText
.text();
68 w
= $container
.width();
72 if ( options
.matchText
) {
73 if ( !( text
in matchTextCache
) ) {
74 matchTextCache
[ text
] = {};
76 if ( !( options
.matchText
in matchTextCache
[ text
] ) ) {
77 matchTextCache
[ text
][ options
.matchText
] = {};
79 if ( !( w
in matchTextCache
[ text
][ options
.matchText
] ) ) {
80 matchTextCache
[ text
][ options
.matchText
][ w
] = {};
82 if ( options
.position
in matchTextCache
[ text
][ options
.matchText
][ w
] ) {
83 $container
.html( matchTextCache
[ text
][ options
.matchText
][ w
][ options
.position
] );
84 if ( options
.tooltip
) {
85 $container
.attr( 'title', text
);
90 if ( !( text
in cache
) ) {
93 if ( !( w
in cache
[ text
] ) ) {
94 cache
[ text
][ w
] = {};
96 if ( options
.position
in cache
[ text
][ w
] ) {
97 $container
.html( cache
[ text
][ w
][ options
.position
] );
98 if ( options
.tooltip
) {
99 $container
.attr( 'title', text
);
105 if ( $trimmableText
.width() + pw
> w
) {
106 switch ( options
.position
) {
108 // Use binary search-like technique for efficiency
110 r
= trimmableText
.length
;
112 m
= Math
.ceil( ( l
+ r
) / 2 );
113 $trimmableText
.text( trimmableText
.slice( 0, m
) + '...' );
114 if ( $trimmableText
.width() + pw
> w
) {
121 $trimmableText
.text( trimmableText
.slice( 0, l
) + '...' );
124 // TODO: Use binary search like for 'right'
125 i
= [ Math
.round( trimmableText
.length
/ 2 ), Math
.round( trimmableText
.length
/ 2 ) ];
126 // Begin with making the end shorter
128 while ( $trimmableText
.outerWidth() + pw
> w
&& i
[ 0 ] > 0 ) {
129 $trimmableText
.text( trimmableText
.slice( 0, i
[ 0 ] ) + '...' + trimmableText
.slice( i
[ 1 ] ) );
130 // Alternate between trimming the end and begining
132 // Make the begining shorter
136 // Make the end shorter
143 // TODO: Use binary search like for 'right'
145 while ( $trimmableText
.outerWidth() + pw
> w
&& r
< trimmableText
.length
) {
146 $trimmableText
.text( '...' + trimmableText
.slice( r
) );
152 if ( options
.tooltip
) {
153 $container
.attr( 'title', text
);
155 if ( options
.matchText
) {
156 $container
.highlightText( options
.matchText
);
157 matchTextCache
[ text
][ options
.matchText
][ w
][ options
.position
] = $container
.html();
159 cache
[ text
][ w
][ options
.position
] = $container
.html();
168 * @mixins jQuery.plugin.autoEllipsis