PageRenderTime 80ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/jQuery.dotdotdot/1.6.9/jquery.dotdotdot.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 645 lines | 555 code | 71 blank | 19 comment | 126 complexity | bae4ad411118962cc1903b11addca65a MD5 | raw file
  1. /*
  2. * jQuery dotdotdot 1.6.9
  3. *
  4. * Copyright (c) 2013 Fred Heusschen
  5. * www.frebsite.nl
  6. *
  7. * Plugin website:
  8. * dotdotdot.frebsite.nl
  9. *
  10. * Dual licensed under the MIT and GPL licenses.
  11. * http://en.wikipedia.org/wiki/MIT_License
  12. * http://en.wikipedia.org/wiki/GNU_General_Public_License
  13. */
  14. (function( $, undef )
  15. {
  16. if ( $.fn.dotdotdot )
  17. {
  18. return;
  19. }
  20. $.fn.dotdotdot = function( o )
  21. {
  22. if ( this.length == 0 )
  23. {
  24. $.fn.dotdotdot.debug( 'No element found for "' + this.selector + '".' );
  25. return this;
  26. }
  27. if ( this.length > 1 )
  28. {
  29. return this.each(
  30. function()
  31. {
  32. $(this).dotdotdot( o );
  33. }
  34. );
  35. }
  36. var $dot = this;
  37. if ( $dot.data( 'dotdotdot' ) )
  38. {
  39. $dot.trigger( 'destroy.dot' );
  40. }
  41. $dot.data( 'dotdotdot-style', $dot.attr( 'style' ) || '' );
  42. $dot.css( 'word-wrap', 'break-word' );
  43. if ($dot.css( 'white-space' ) === 'nowrap')
  44. {
  45. $dot.css( 'white-space', 'normal' );
  46. }
  47. $dot.bind_events = function()
  48. {
  49. $dot.bind(
  50. 'update.dot',
  51. function( e, c )
  52. {
  53. e.preventDefault();
  54. e.stopPropagation();
  55. opts.maxHeight = ( typeof opts.height == 'number' )
  56. ? opts.height
  57. : getTrueInnerHeight( $dot );
  58. opts.maxHeight += opts.tolerance;
  59. if ( typeof c != 'undefined' )
  60. {
  61. if ( typeof c == 'string' || c instanceof HTMLElement )
  62. {
  63. c = $('<div />').append( c ).contents();
  64. }
  65. if ( c instanceof $ )
  66. {
  67. orgContent = c;
  68. }
  69. }
  70. $inr = $dot.wrapInner( '<div class="dotdotdot" />' ).children();
  71. $inr.empty()
  72. .append( orgContent.clone( true ) )
  73. .find( 'br' ).replaceWith( ' <br /> ' ).end()
  74. .css({
  75. 'height' : 'auto',
  76. 'width' : 'auto',
  77. 'border' : 'none',
  78. 'padding' : 0,
  79. 'margin' : 0
  80. });
  81. var after = false,
  82. trunc = false;
  83. if ( conf.afterElement )
  84. {
  85. after = conf.afterElement.clone( true );
  86. after.show();
  87. conf.afterElement.remove();
  88. }
  89. if ( test( $inr, opts ) )
  90. {
  91. if ( opts.wrap == 'children' )
  92. {
  93. trunc = children( $inr, opts, after );
  94. }
  95. else
  96. {
  97. trunc = ellipsis( $inr, $dot, $inr, opts, after );
  98. }
  99. }
  100. $inr.replaceWith( $inr.contents() );
  101. $inr = null;
  102. if ( $.isFunction( opts.callback ) )
  103. {
  104. opts.callback.call( $dot[ 0 ], trunc, orgContent );
  105. }
  106. conf.isTruncated = trunc;
  107. return trunc;
  108. }
  109. ).bind(
  110. 'isTruncated.dot',
  111. function( e, fn )
  112. {
  113. e.preventDefault();
  114. e.stopPropagation();
  115. if ( typeof fn == 'function' )
  116. {
  117. fn.call( $dot[ 0 ], conf.isTruncated );
  118. }
  119. return conf.isTruncated;
  120. }
  121. ).bind(
  122. 'originalContent.dot',
  123. function( e, fn )
  124. {
  125. e.preventDefault();
  126. e.stopPropagation();
  127. if ( typeof fn == 'function' )
  128. {
  129. fn.call( $dot[ 0 ], orgContent );
  130. }
  131. return orgContent;
  132. }
  133. ).bind(
  134. 'destroy.dot',
  135. function( e )
  136. {
  137. e.preventDefault();
  138. e.stopPropagation();
  139. $dot.unwatch()
  140. .unbind_events()
  141. .empty()
  142. .append( orgContent )
  143. .attr( 'style', $dot.data( 'dotdotdot-style' ) || '' )
  144. .data( 'dotdotdot', false );
  145. }
  146. );
  147. return $dot;
  148. }; // /bind_events
  149. $dot.unbind_events = function()
  150. {
  151. $dot.unbind('.dot');
  152. return $dot;
  153. }; // /unbind_events
  154. $dot.watch = function()
  155. {
  156. $dot.unwatch();
  157. if ( opts.watch == 'window' )
  158. {
  159. var $window = $(window),
  160. _wWidth = $window.width(),
  161. _wHeight = $window.height();
  162. $window.bind(
  163. 'resize.dot' + conf.dotId,
  164. function()
  165. {
  166. if ( _wWidth != $window.width() || _wHeight != $window.height() || !opts.windowResizeFix )
  167. {
  168. _wWidth = $window.width();
  169. _wHeight = $window.height();
  170. if ( watchInt )
  171. {
  172. clearInterval( watchInt );
  173. }
  174. watchInt = setTimeout(
  175. function()
  176. {
  177. $dot.trigger( 'update.dot' );
  178. }, 10
  179. );
  180. }
  181. }
  182. );
  183. }
  184. else
  185. {
  186. watchOrg = getSizes( $dot );
  187. watchInt = setInterval(
  188. function()
  189. {
  190. var watchNew = getSizes( $dot );
  191. if ( watchOrg.width != watchNew.width ||
  192. watchOrg.height != watchNew.height )
  193. {
  194. $dot.trigger( 'update.dot' );
  195. watchOrg = getSizes( $dot );
  196. }
  197. }, 100
  198. );
  199. }
  200. return $dot;
  201. };
  202. $dot.unwatch = function()
  203. {
  204. $(window).unbind( 'resize.dot' + conf.dotId );
  205. if ( watchInt )
  206. {
  207. clearInterval( watchInt );
  208. }
  209. return $dot;
  210. };
  211. var orgContent = $dot.contents(),
  212. opts = $.extend( true, {}, $.fn.dotdotdot.defaults, o ),
  213. conf = {},
  214. watchOrg = {},
  215. watchInt = null,
  216. $inr = null;
  217. if ( !( opts.lastCharacter.remove instanceof Array ) )
  218. {
  219. opts.lastCharacter.remove = $.fn.dotdotdot.defaultArrays.lastCharacter.remove;
  220. }
  221. if ( !( opts.lastCharacter.noEllipsis instanceof Array ) )
  222. {
  223. opts.lastCharacter.noEllipsis = $.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis;
  224. }
  225. conf.afterElement = getElement( opts.after, $dot );
  226. conf.isTruncated = false;
  227. conf.dotId = dotId++;
  228. $dot.data( 'dotdotdot', true )
  229. .bind_events()
  230. .trigger( 'update.dot' );
  231. if ( opts.watch )
  232. {
  233. $dot.watch();
  234. }
  235. return $dot;
  236. };
  237. // public
  238. $.fn.dotdotdot.defaults = {
  239. 'ellipsis' : '... ',
  240. 'wrap' : 'word',
  241. 'fallbackToLetter' : true,
  242. 'lastCharacter' : {},
  243. 'tolerance' : 0,
  244. 'callback' : null,
  245. 'after' : null,
  246. 'height' : null,
  247. 'watch' : false,
  248. 'windowResizeFix' : true
  249. };
  250. $.fn.dotdotdot.defaultArrays = {
  251. 'lastCharacter' : {
  252. 'remove' : [ ' ', '\u3000', ',', ';', '.', '!', '?' ],
  253. 'noEllipsis' : []
  254. }
  255. };
  256. $.fn.dotdotdot.debug = function( msg ) {};
  257. // private
  258. var dotId = 1;
  259. function children( $elem, o, after )
  260. {
  261. var $elements = $elem.children(),
  262. isTruncated = false;
  263. $elem.empty();
  264. for ( var a = 0, l = $elements.length; a < l; a++ )
  265. {
  266. var $e = $elements.eq( a );
  267. $elem.append( $e );
  268. if ( after )
  269. {
  270. $elem.append( after );
  271. }
  272. if ( test( $elem, o ) )
  273. {
  274. $e.remove();
  275. isTruncated = true;
  276. break;
  277. }
  278. else
  279. {
  280. if ( after )
  281. {
  282. after.detach();
  283. }
  284. }
  285. }
  286. return isTruncated;
  287. }
  288. function ellipsis( $elem, $d, $i, o, after )
  289. {
  290. var $elements = $elem.contents(),
  291. isTruncated = false;
  292. $elem.empty();
  293. var notx = 'table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style';
  294. for ( var a = 0, l = $elements.length; a < l; a++ )
  295. {
  296. if ( isTruncated )
  297. {
  298. break;
  299. }
  300. var e = $elements[ a ],
  301. $e = $(e);
  302. if ( typeof e == 'undefined' || ( e.nodeType == 3 && $.trim( e.data ).length == 0 ) )
  303. {
  304. continue;
  305. }
  306. $elem.append( $e );
  307. if ( after )
  308. {
  309. $elem[ $elem.is( notx ) ? 'after' : 'append' ]( after );
  310. }
  311. if ( test( $i, o ) )
  312. {
  313. if ( e.nodeType == 3 ) // node is TEXT
  314. {
  315. isTruncated = ellipsisElement( $e, $d, $i, o, after );
  316. }
  317. else
  318. {
  319. isTruncated = ellipsis( $e, $d, $i, o, after );
  320. }
  321. if ( !isTruncated )
  322. {
  323. $e.remove();
  324. isTruncated = true;
  325. }
  326. }
  327. if ( !isTruncated )
  328. {
  329. if ( after )
  330. {
  331. after.detach();
  332. }
  333. }
  334. }
  335. return isTruncated;
  336. }
  337. function ellipsisElement( $e, $d, $i, o, after )
  338. {
  339. var e = $e[ 0 ];
  340. if ( !e )
  341. {
  342. return false;
  343. }
  344. var txt = getTextContent( e ),
  345. space = ( txt.indexOf(' ') !== -1 ) ? ' ' : '\u3000',
  346. separator = ( o.wrap == 'letter' ) ? '' : space,
  347. textArr = txt.split( separator ),
  348. position = -1,
  349. midPos = -1,
  350. startPos = 0,
  351. endPos = textArr.length - 1;
  352. // Only one word
  353. if ( o.fallbackToLetter && startPos == 0 && endPos == 0 )
  354. {
  355. separator = '';
  356. textArr = txt.split( separator );
  357. endPos = textArr.length - 1;
  358. }
  359. while ( startPos <= endPos && !( startPos == 0 && endPos == 0 ) )
  360. {
  361. var m = Math.floor( ( startPos + endPos ) / 2 );
  362. if ( m == midPos )
  363. {
  364. break;
  365. }
  366. midPos = m;
  367. setTextContent( e, textArr.slice( 0, midPos + 1 ).join( separator ) + o.ellipsis );
  368. if ( !test( $i, o ) )
  369. {
  370. position = midPos;
  371. startPos = midPos;
  372. }
  373. else
  374. {
  375. endPos = midPos;
  376. // Fallback to letter
  377. if (o.fallbackToLetter && startPos == 0 && endPos == 0 )
  378. {
  379. separator = '';
  380. textArr = textArr[ 0 ].split( separator );
  381. position = -1;
  382. midPos = -1;
  383. startPos = 0;
  384. endPos = textArr.length - 1;
  385. }
  386. }
  387. }
  388. if ( position != -1 && !( textArr.length == 1 && textArr[ 0 ].length == 0 ) )
  389. {
  390. txt = addEllipsis( textArr.slice( 0, position + 1 ).join( separator ), o );
  391. setTextContent( e, txt );
  392. }
  393. else
  394. {
  395. var $w = $e.parent();
  396. $e.remove();
  397. var afterLength = ( after && after.closest($w).length ) ? after.length : 0;
  398. if ( $w.contents().length > afterLength )
  399. {
  400. e = findLastTextNode( $w.contents().eq( -1 - afterLength ), $d );
  401. }
  402. else
  403. {
  404. e = findLastTextNode( $w, $d, true );
  405. if ( !afterLength )
  406. {
  407. $w.remove();
  408. }
  409. }
  410. if ( e )
  411. {
  412. txt = addEllipsis( getTextContent( e ), o );
  413. setTextContent( e, txt );
  414. if ( afterLength && after )
  415. {
  416. $(e).parent().append( after );
  417. }
  418. }
  419. }
  420. return true;
  421. }
  422. function test( $i, o )
  423. {
  424. return $i.innerHeight() > o.maxHeight;
  425. }
  426. function addEllipsis( txt, o )
  427. {
  428. while( $.inArray( txt.slice( -1 ), o.lastCharacter.remove ) > -1 )
  429. {
  430. txt = txt.slice( 0, -1 );
  431. }
  432. if ( $.inArray( txt.slice( -1 ), o.lastCharacter.noEllipsis ) < 0 )
  433. {
  434. txt += o.ellipsis;
  435. }
  436. return txt;
  437. }
  438. function getSizes( $d )
  439. {
  440. return {
  441. 'width' : $d.innerWidth(),
  442. 'height': $d.innerHeight()
  443. };
  444. }
  445. function setTextContent( e, content )
  446. {
  447. if ( e.innerText )
  448. {
  449. e.innerText = content;
  450. }
  451. else if ( e.nodeValue )
  452. {
  453. e.nodeValue = content;
  454. }
  455. else if (e.textContent)
  456. {
  457. e.textContent = content;
  458. }
  459. }
  460. function getTextContent( e )
  461. {
  462. if ( e.innerText )
  463. {
  464. return e.innerText;
  465. }
  466. else if ( e.nodeValue )
  467. {
  468. return e.nodeValue;
  469. }
  470. else if ( e.textContent )
  471. {
  472. return e.textContent;
  473. }
  474. else
  475. {
  476. return "";
  477. }
  478. }
  479. function getPrevNode( n )
  480. {
  481. do
  482. {
  483. n = n.previousSibling;
  484. }
  485. while ( n && n.nodeType !== 1 && n.nodeType !== 3 );
  486. return n;
  487. }
  488. function findLastTextNode( $el, $top, excludeCurrent )
  489. {
  490. var e = $el && $el[ 0 ], p;
  491. if ( e )
  492. {
  493. if ( !excludeCurrent )
  494. {
  495. if ( e.nodeType === 3 )
  496. {
  497. return e;
  498. }
  499. if ( $.trim( $el.text() ) )
  500. {
  501. return findLastTextNode( $el.contents().last(), $top );
  502. }
  503. }
  504. p = getPrevNode( e );
  505. while ( !p )
  506. {
  507. $el = $el.parent();
  508. if ( $el.is( $top ) || !$el.length )
  509. {
  510. return false;
  511. }
  512. p = getPrevNode( $el[0] );
  513. }
  514. if ( p )
  515. {
  516. return findLastTextNode( $(p), $top );
  517. }
  518. }
  519. return false;
  520. }
  521. function getElement( e, $i )
  522. {
  523. if ( !e )
  524. {
  525. return false;
  526. }
  527. if ( typeof e === 'string' )
  528. {
  529. e = $(e, $i);
  530. return ( e.length )
  531. ? e
  532. : false;
  533. }
  534. return !e.jquery
  535. ? false
  536. : e;
  537. }
  538. function getTrueInnerHeight( $el )
  539. {
  540. var h = $el.innerHeight(),
  541. a = [ 'paddingTop', 'paddingBottom' ];
  542. for ( var z = 0, l = a.length; z < l; z++ )
  543. {
  544. var m = parseInt( $el.css( a[ z ] ), 10 );
  545. if ( isNaN( m ) )
  546. {
  547. m = 0;
  548. }
  549. h -= m;
  550. }
  551. return h;
  552. }
  553. // override jQuery.html
  554. var _orgHtml = $.fn.html;
  555. $.fn.html = function( str )
  556. {
  557. if ( str != undef && !$.isFunction( str ) && this.data( 'dotdotdot' ) )
  558. {
  559. return this.trigger( 'update', [ str ] );
  560. }
  561. return _orgHtml.apply( this, arguments );
  562. };
  563. // override jQuery.text
  564. var _orgText = $.fn.text;
  565. $.fn.text = function( str )
  566. {
  567. if ( str != undef && !$.isFunction( str ) && this.data( 'dotdotdot' ) )
  568. {
  569. str = $( '<div />' ).text( str ).html();
  570. return this.trigger( 'update', [ str ] );
  571. }
  572. return _orgText.apply( this, arguments );
  573. };
  574. })( jQuery );