From a1c7d57cb4d5315d623eaf20846426041b102da6 Mon Sep 17 00:00:00 2001 From: FrDH Date: Tue, 14 Nov 2017 23:36:09 +0100 Subject: [PATCH] v3.1 callback and height option, bugfix in height calculation --- bower.json | 2 +- composer.json | 2 +- dist/jquery.dotdotdot.js | 4 +-- package.json | 2 +- src/jquery.dotdotdot.js | 68 ++++++++++++++++++++++++++-------------- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/bower.json b/bower.json index ce30e7d..bee6df7 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name" : "jQuery.dotdotdot", - "version" : "3.0.5", + "version" : "3.1.0", "main" : "dist/jquery.dotdotdot.js", "authors" : "Fred Heusschen ", "license" : "CC-BY-NC-4.0", diff --git a/composer.json b/composer.json index 3de4629..8fcfa4a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name" : "jQuery.dotdotdot", - "version" : "3.0.5", + "version" : "3.1.0", "authors" : "Fred Heusschen ", "license" : "CC-BY-NC-4.0", "description" : "Dotdotdot is an advanced jQuery plugin for truncating multiple line content with an ellipsis.", diff --git a/dist/jquery.dotdotdot.js b/dist/jquery.dotdotdot.js index 060da9b..17dc825 100644 --- a/dist/jquery.dotdotdot.js +++ b/dist/jquery.dotdotdot.js @@ -8,7 +8,7 @@ } }(this, function(jQuery) { /* - * jQuery dotdotdot 3.0.5 + * jQuery dotdotdot 3.1.0 * @requires jQuery 1.7.0 or later * * dotdotdot.frebsite.nl @@ -19,6 +19,6 @@ * License: CC-BY-NC-4.0 * http://creativecommons.org/licenses/by-nc/4.0/ */ -!function(t){"use strict";function e(){a=t(window),s={},r={},o={},t.each([s,r,o],function(t,e){e.add=function(t){t=t.split(" ");for(var n=0,i=t.length;ni)){t[n]=function(t,e){this.$dot=t,this.api=["getInstance","truncate","restore","destroy","watch","unwatch"],this.opts=e;var i=this.$dot.data(n);return i&&i.destroy(),this.init(),this.truncate(),this.opts.watch&&this.watch(),this},t[n].version=i,t[n].uniqueId=0,t[n].defaults={ellipsis:"… ",truncate:"word",tolerance:0,keep:null,watch:"window"},t[n].prototype={init:function(){this.watchTimeout=null,this.watchInterval=null,this.uniqueId=t[n].uniqueId++,this.originalContent=this.$dot.contents(),this.originalStyle=this.$dot.attr("style")||"",this.maxHeight=this._getMaxHeight()+this.opts.tolerance,"break-word"!==this.$dot.css("word-wrap")&&this.$dot.css("word-wrap","break-word"),"nowrap"===this.$dot.css("white-space")&&this.$dot.css("white-space","normal")},getInstance:function(){return this},truncate:function(){var e=this;this.$inner=this.$dot.wrapInner("
").children().css({display:"block",height:"auto",width:"auto",border:"none",padding:0,margin:0}),this.$inner.contents().detach().end().append(this.originalContent.clone(!0)),this.$inner.find("script, style").addClass(s.keep),this.opts.keep&&this.$inner.find(this.opts.keep).addClass(s.keep),this.$inner.find("*").not("."+s.keep).add(this.$inner).contents().each(function(){var n=this,i=t(this);if(3==n.nodeType){if(i.prev().is("table, thead, tfoot, tr, th, td, dl, dt, dd, ul, ol, li, video"))return void i.remove();if(i.parent().contents().length>1){var r=t(''+e.__getTextContent(n)+"").css({display:"inline",height:"auto",width:"auto",border:"none",padding:0,margin:0});i.replaceWith(r)}}else 8==n.nodeType&&i.remove()});var n=this._truncateNode(this.$dot);return this.$dot[n?"addClass":"removeClass"](s.truncated),this.$inner.find("."+s.text).each(function(){t(this).replaceWith(t(this).contents())}),this.$inner.find("."+s.keep).removeClass(s.keep),this.$inner.replaceWith(this.$inner.contents()),this.$inner=null,n},restore:function(){this.unwatch(),this.$dot.contents().detach().end().append(this.originalContent).attr("style",this.originalStyle).removeClass(s.truncated)},destroy:function(){this.restore(),this.$dot.data(n,null)},watch:function(){var t=this;this.unwatch();var e={};"window"==this.opts.watch?a.on(o.resize+t.uniqueId,function(n){t.watchTimeout&&clearTimeout(t.watchTimeout),t.watchTimeout=setTimeout(function(){e=t._watchSizes(e,a,"width","height")},100)}):this.watchInterval=setInterval(function(){e=t._watchSizes(e,t.$dot,"innerWidth","innerHeight")},500)},unwatch:function(){a.off(o.resize+this.uniqueId),this.watchInterval&&clearInterval(this.watchInterval),this.watchTimeout&&clearTimeout(this.watchTimeout)},_api:function(){var e=this,n={};return t.each(this.api,function(t){var i=this;n[i]=function(){var t=e[i].apply(e,arguments);return"undefined"==typeof t?n:t}}),n},_truncateNode:function(e){var n=this,i=!1,r=!1;return t(e.children().get().reverse()).not("."+s.keep).each(function(){var e=(t(this).contents()[0],t(this));if(!i&&!e.hasClass(s.keep)){if(e.children().length)i=n._truncateNode(e);else if(!n._fits()||r){var o=t("").css("display","none");if(e.replaceWith(o),e.detach(),n._fits()){if("node"==n.opts.truncate)return!0;o.replaceWith(e),i=n._truncateWord(e),i||(r=!0,e.detach())}else o.remove()}e.contents().length||e.remove()}}),i},_truncateWord:function(t){var e=t.contents()[0];if(!e)return!1;for(var n=this,i=this.__getTextContent(e),s=i.indexOf(" ")!==-1?" ":" ",r=i.split(s),o="",a=r.length;a>=0;a--){if(o=r.slice(0,a).join(s),0==a)return"letter"==n.opts.truncate&&(n.__setTextContent(e,r.slice(0,a+1).join(s)),n._truncateLetter(e));if(o.length&&(n.__setTextContent(e,n._addEllipsis(o)),n._fits()))return"letter"!=n.opts.truncate||(n.__setTextContent(e,r.slice(0,a+1).join(s)),n._truncateLetter(e))}return!1},_truncateLetter:function(t){for(var e=this,n=this.__getTextContent(t),i=n.split(""),s="",r=i.length;r>=0;r--)if(s=i.slice(0,r).join(""),s.length&&(e.__setTextContent(t,e._addEllipsis(s)),e._fits()))return!0;return!1},_fits:function(){return this.$inner.innerHeight()<=this.maxHeight},_addEllipsis:function(e){for(var n=[" "," ",",",";",".","!","?"];t.inArray(e.slice(-1),n)>-1;)e=e.slice(0,-1);return e+=this.opts.ellipsis},_getMaxHeight:function(){for(var t=["height","maxHeight"],e=0,n=0;ni)){t[n]=function(t,e){this.$dot=t,this.api=["getInstance","truncate","restore","destroy","watch","unwatch"],this.opts=e;var i=this.$dot.data(n);return i&&i.destroy(),this.init(),this.truncate(),this.opts.watch&&this.watch(),this},t[n].version=i,t[n].uniqueId=0,t[n].defaults={ellipsis:"… ",callback:function(t){},truncate:"word",tolerance:0,keep:null,watch:"window",height:null},t[n].prototype={init:function(){this.watchTimeout=null,this.watchInterval=null,this.uniqueId=t[n].uniqueId++,this.originalContent=this.$dot.contents(),this.originalStyle=this.$dot.attr("style")||"","break-word"!==this.$dot.css("word-wrap")&&this.$dot.css("word-wrap","break-word"),"nowrap"===this.$dot.css("white-space")&&this.$dot.css("white-space","normal"),null===this.opts.height&&(this.opts.height=this._getMaxHeight())},getInstance:function(){return this},truncate:function(){var e=this;this.$inner=this.$dot.wrapInner("
").children().css({display:"block",height:"auto",width:"auto",border:"none",padding:0,margin:0}),this.$inner.contents().detach().end().append(this.originalContent.clone(!0)),this.$inner.find("script, style").addClass(s.keep),this.opts.keep&&this.$inner.find(this.opts.keep).addClass(s.keep),this.$inner.find("*").not("."+s.keep).add(this.$inner).contents().each(function(){var n=this,i=t(this);if(3==n.nodeType){if(i.parent().is("table, thead, tfoot, tr, dl, ul, ol, video"))return void i.remove();if(i.parent().contents().length>1){var r=t(''+e.__getTextContent(n)+"").css({display:"inline",height:"auto",width:"auto",border:"none",padding:0,margin:0});i.replaceWith(r)}}else 8==n.nodeType&&i.remove()}),this.maxHeight=this._getMaxHeight();var n=this._truncateNode(this.$dot);return this.$dot[n?"addClass":"removeClass"](s.truncated),this.$inner.find("."+s.text).each(function(){t(this).replaceWith(t(this).contents())}),this.$inner.find("."+s.keep).removeClass(s.keep),this.$inner.replaceWith(this.$inner.contents()),this.$inner=null,this.opts.callback.call(this.$dot[0],n),n},restore:function(){this.unwatch(),this.$dot.contents().detach().end().append(this.originalContent).attr("style",this.originalStyle).removeClass(s.truncated)},destroy:function(){this.restore(),this.$dot.data(n,null)},watch:function(){var t=this;this.unwatch();var e={};"window"==this.opts.watch?h.on(o.resize+t.uniqueId,function(n){t.watchTimeout&&clearTimeout(t.watchTimeout),t.watchTimeout=setTimeout(function(){e=t._watchSizes(e,h,"width","height")},100)}):this.watchInterval=setInterval(function(){e=t._watchSizes(e,t.$dot,"innerWidth","innerHeight")},500)},unwatch:function(){h.off(o.resize+this.uniqueId),this.watchInterval&&clearInterval(this.watchInterval),this.watchTimeout&&clearTimeout(this.watchTimeout)},_api:function(){var e=this,n={};return t.each(this.api,function(t){var i=this;n[i]=function(){var t=e[i].apply(e,arguments);return"undefined"==typeof t?n:t}}),n},_truncateNode:function(e){var n=this,i=!1,r=!1;return t(e.children().get().reverse()).not("."+s.keep).each(function(){var e=(t(this).contents()[0],t(this));if(!i&&!e.hasClass(s.keep)){if(e.children().length)i=n._truncateNode(e);else if(!n._fits()||r){var o=t("").css("display","none");if(e.replaceWith(o),e.detach(),n._fits()){if("node"==n.opts.truncate)return!0;o.replaceWith(e),i=n._truncateWord(e),i||(r=!0,e.detach())}else o.remove()}e.contents().length||e.remove()}}),i},_truncateWord:function(t){var e=t.contents()[0];if(!e)return!1;for(var n=this,i=this.__getTextContent(e),s=i.indexOf(" ")!==-1?" ":" ",r=i.split(s),o="",h=r.length;h>=0;h--){if(o=r.slice(0,h).join(s),0==h)return"letter"==n.opts.truncate&&(n.__setTextContent(e,r.slice(0,h+1).join(s)),n._truncateLetter(e));if(o.length&&(n.__setTextContent(e,n._addEllipsis(o)),n._fits()))return"letter"!=n.opts.truncate||(n.__setTextContent(e,r.slice(0,h+1).join(s)),n._truncateLetter(e))}return!1},_truncateLetter:function(t){for(var e=this,n=this.__getTextContent(t),i=n.split(""),s="",r=i.length;r>=0;r--)if(s=i.slice(0,r).join(""),s.length&&(e.__setTextContent(t,e._addEllipsis(s)),e._fits()))return!0;return!1},_fits:function(){return this.$inner.innerHeight()<=this.maxHeight+this.opts.tolerance},_addEllipsis:function(e){for(var n=[" "," ",",",";",".","!","?"];t.inArray(e.slice(-1),n)>-1;)e=e.slice(0,-1);return e+=this.opts.ellipsis},_getMaxHeight:function(){if("number"==typeof this.opts.height)return this.opts.height;for(var t=["maxHeight","height"],e=0,n=0;n", "license" : "CC-BY-NC-4.0", diff --git a/src/jquery.dotdotdot.js b/src/jquery.dotdotdot.js index 30efe5b..8661532 100644 --- a/src/jquery.dotdotdot.js +++ b/src/jquery.dotdotdot.js @@ -1,5 +1,5 @@ /* - * jQuery dotdotdot 3.0.5 + * jQuery dotdotdot 3.1.0 * @requires jQuery 1.7.0 or later * * dotdotdot.frebsite.nl @@ -15,7 +15,7 @@ 'use strict'; var _PLUGIN_ = 'dotdotdot'; - var _VERSION_ = '3.0.5'; + var _VERSION_ = '3.1.0'; if ( $[ _PLUGIN_ ] && $[ _PLUGIN_ ].version > _VERSION_ ) { @@ -55,10 +55,12 @@ $[ _PLUGIN_ ].defaults = { ellipsis : '\u2026 ', + callback : function( isTruncated ) {}, truncate : 'word', tolerance : 0, keep : null, - watch : 'window' + watch : 'window', + height : null }; @@ -71,8 +73,7 @@ this.uniqueId = $[ _PLUGIN_ ].uniqueId++; this.originalContent = this.$dot.contents(); this.originalStyle = this.$dot.attr( 'style' ) || ''; - this.maxHeight = this._getMaxHeight() + this.opts.tolerance; - + if ( this.$dot.css( 'word-wrap' ) !== 'break-word' ) { this.$dot.css( 'word-wrap', 'break-word' ); @@ -81,6 +82,11 @@ { this.$dot.css( 'white-space', 'normal' ); } + + if ( this.opts.height === null ) + { + this.opts.height = this._getMaxHeight(); + } }, getInstance: function() @@ -141,11 +147,12 @@ var e = this, $e = $(this); + // Text nodes if ( e.nodeType == 3 ) { // Remove whitespace where it does not take up space in the DOM - if ( $e.prev().is( 'table, thead, tfoot, tr, th, td, dl, dt, dd, ul, ol, li, video' ) ) + if ( $e.parent().is( 'table, thead, tfoot, tr, dl, ul, ol, video' ) ) { $e.remove(); return; @@ -168,7 +175,7 @@ } } - // Remove comments + // Comment nodes else if ( e.nodeType == 8 ) { $e.remove(); @@ -178,6 +185,9 @@ ); + this.maxHeight = this._getMaxHeight(); + + // Truncate the text var isTruncated = this._truncateNode( this.$dot ); this.$dot[ isTruncated ? 'addClass' : 'removeClass' ]( _c.truncated ); @@ -204,7 +214,7 @@ this.$inner.replaceWith( this.$inner.contents() ); this.$inner = null; - + this.opts.callback.call( this.$dot[ 0 ], isTruncated ); return isTruncated; }, @@ -456,7 +466,7 @@ _fits: function() { - return ( this.$inner.innerHeight() <= this.maxHeight ); + return ( this.$inner.innerHeight() <= this.maxHeight + this.opts.tolerance ); }, _addEllipsis: function( txt ) @@ -474,37 +484,47 @@ _getMaxHeight: function() { + if ( typeof this.opts.height == 'number' ) + { + return this.opts.height; + } + // Find smallest CSS height - var arr = [ 'height', 'maxHeight' ], + var arr = [ 'maxHeight', 'height' ], hgh = 0; for ( var a = 0; a < arr.length; a++ ) { - var h = window.getComputedStyle( this.$dot[ 0 ] )[ arr[ a ] ]; - if ( h.slice( -2 ) == 'px' ) + hgh = window.getComputedStyle( this.$dot[ 0 ] )[ arr[ a ] ]; + if ( hgh.slice( -2 ) == 'px' ) { - h = parseInt( h, 10 ); - hgh = hgh ? Math.min( hgh, h ) : h; + hgh = parseFloat( hgh ); + break; } } // Remove padding-top/bottom when needed. + var arr = []; switch ( this.$dot.css( 'boxSizing' ) ) { - case 'padding-box': case 'border-box': - var arr = [ 'paddingTop', 'paddingBottom' ]; + arr.push( 'borderTopWidth' ); + arr.push( 'borderBottomWidth' ); + // no break -> padding needs to be added too - for ( var a = 0; a < arr.length; a++ ) - { - var p = window.getComputedStyle( this.$dot[ 0 ] )[ arr[ a ] ]; - if ( p.slice( -2 ) == 'px' ) - { - hgh -= parseInt( p, 10 ); - } - } + case 'padding-box': + arr.push( 'paddingTop' ); + arr.push( 'paddingBottom' ); break; } + for ( var a = 0; a < arr.length; a++ ) + { + var p = window.getComputedStyle( this.$dot[ 0 ] )[ arr[ a ] ]; + if ( p.slice( -2 ) == 'px' ) + { + hgh -= parseFloat( p ); + } + } // Sanitize return Math.max( hgh, 0 );