snaggs
snaggs

Reputation: 5713

How to truncate text based on element width, angular?

I have String text and I want to show how many words I hide based on screen width.

This is what I have so far:

 app.filter('words', function () {
        return function (input, words) {
            if (isNaN(words)) return input;
            if (words <= 0) return '';
            if (input) {
                var inputWords = input.split(/\s+/);
                if (inputWords.length > words) {

                    var theLength = inputWords.length - words;

                    input = inputWords.slice(0, words).join(' ') + ' + ' + theLength;
                }
            }
            return input;
        };
    });

This filter works for fixed count of words. If words = 5 means we can see only 5 words and other will be hidden.

But I looking for way to make words number dynamic based on element width. For example for <div> width 200 px I show 12 words, (maybe more maybe less), for 40px - or zero words (if word too long) or one word,

I think I need mix with some directive that should take element width and calculate words number.

This is a Demo:

DEMO

enter image description here

Thank you very much for help,

Upvotes: 0

Views: 3449

Answers (1)

Jerrad
Jerrad

Reputation: 5290

Here's a directive I whipped up:

app.directive('wordCount', function($compile){
    return{
        restrict: 'E',
        replace: true,
        scope: {
            width: '=',
            text: '='
        },
        template: '<div style ="border-style: solid; width:{{width}}px"><span>{{text}}</span></div>',        
        link: function(scope, element, attrs){            
            scope.$watch('width', function(value){          
                if(isNaN(scope.width) || scope.width < 0)
                    return;
                var numWords = Math.floor(scope.width / 15); 
                var inputWords = scope.text.split(/\s+/);
                var theLength = inputWords.length - numWords;
                console.log('Element width: ' + scope.width);
                console.log("# of words: " + inputWords.length);
                console.log("# of words to show: " + numWords);

                element[0].innerHTML = inputWords.slice(0, numWords).join(' ') + ' + ' + theLength;          
            });
        }
    };
});

The logic is all in the link function, and it mostly uses your own code. Usage is like this:

<word-count width="<width>" text="<text>"></word-count>

where <width> is the width you want the div to be, and <text> is the text you want displayed. I used a simple formula of width/15 to determine the number of words to show. You would probably want to come up with something a little more sophisticated.

Here's a Fiddle showing it in action.

Upvotes: 3

Related Questions