PageRenderTime 68ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/files/jquery.dotdotdot/1.6.14/jquery.dotdotdot.js

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