0
votes

I'm building an Emberjs app, and I have an HTML element that contains text which often overflows the element, so I want to truncate the text and append an ellipses.

Here's my HTML element and CSS:

<div class="elementClass">{{textValue}}</div>

.elementClass {
     height: 100px;
}

Here's the JavaScript function I'm using to trim the last three characters of the text until the scrollHeight is no longer greater than the height:

function truncateElementText($element) {
    var html = $element.html();

    if ($element.height() < $element.prop('scrollHeight')) {
         $element.html(html.substring(html.length - 3, html.length) + '&hellip;');
         truncateElementText($element);
    }
}

Here's the Emberjs view I'm using to call truncateElementText on the element that I want to trim:

App.MyView = Ember.View.extend({
    didInsertElement: function () {
         Ember.run.scheduleOnce('afterRender', this, function() {
               var $element = $('.elementClass');
               truncateElementText($element);
         });
    }  
});

The problem is, truncateElementText seems to be executing before it has access to the $element. It doesn't trim $element the first time the page loads, but it will trim $element if I refresh the browser. If I do console.log($element.html()) at the beginning of didInsertElement, I can see that it has the element and its HTML at that point, so it's not like $element isn't available in the DOM when I select it and pass it to the function.

If I use setTimeout to delay truncateElementText by 50 milliseconds, it works every time, even the first time the page is loaded.

I'm new to Ember, so any and all advice would be greatly appreciated.

Thanks!

2

2 Answers

0
votes

it's not exactly the answer to your question, but have you considered css's ellipsis?

.elementClass {
  text-overflow: ellipsis;
  white-space: nowrap; 
}

That would be much simplier :)

You can try it here: http://www.w3schools.com/cssref/tryit.asp?filename=trycss3_text-overflow

One thing from myself: if I am to modify the content of DOM when using Ember, in 99.9% of the cases it can be avoided.

0
votes

I got it working along the lines of your suggestion, adding also invalidation of the content when window is resized.

I tested it on Chrome with Ember 1.9.1.

Template for the view:

<div class="rawContent" style="display:none">{{model}}</div>
<div class="elementClass"></div>

JS for the view:

App.IndexView = Ember.View.extend({

  didInsertElement: function () {
     var _this = this;
     Ember.run.next(function() {
         _this.truncateElementClass();
     });
     Ember.$(window).on('resize', _this.truncateElementClass);
  },

  willDestroyElement: function(){
     var _this = this;    
     Ember.$(window).off('resize', _this.truncateElementClass);
  },

  truncateElementClass: function(){
    var $element = this.$('.elementClass');
    var $raw = this.$('.rawContent');    
    $element.html($raw.html());
    truncateElementText($element);
  }
});

function truncateElementText($element) {
    var html = $element.html();
    if ($element.height() < $element.prop('scrollHeight')) {
         $element.html(html.substring(0, html.length - 3) + '&hellip;');
         truncateElementText($element);
    }
}

See JsBin for example.