PageRenderTime 73ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/files/jquery.dotdotdot/1.6.15/jquery.dotdotdot.js

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