Note that there are some explanatory texts on larger screens.

plurals
  1. POAngularJS filter causes IE8 to not render two-way binding
    primarykey
    data
    text
    <p>I have a bizarre issue with IE8 where if I try to render a <code>$scope</code> variable in a template via AngularJS's two-way data binding, it won't replace <code>{{child.name}}</code> with the proper value. This surely has something to do with the inefficiency of the following filter:</p> <pre><code> filter('truncate', function() { return function(name) { // It's just easier to use jQuery here var windowWidth = $(window).width(), nameElement = $('a:contains("' + name + '")'), truncPnt = Math.floor(name.length * 0.9); while (nameElement.width() &gt; windowWidth * 0.75 &amp;&amp; truncPnt &gt; 6) { truncPnt = Math.floor(truncPnt * 0.9); name = name.substring(0, truncPnt); nameElement.text(name + ' ...'); } return name; } }); </code></pre> <p>I then use this filter with an <code>ng-repeat</code> with:</p> <pre><code>&lt;a class="entity-name" href="{{child.url}}" title="{{child.name}}" ng-cloak&gt;{{child.name|truncate}}&lt;/a&gt; </code></pre> <p>The overall goal is to have the variable passed into the filter truncated down depending on the width of the screen, replacing any truncated characters with " ...". I'm fairly confident this filter is the cause since I have a similar function that gets called on a <code>.resize()</code> of the <code>$(window)</code> handler, and if I were to take IE8, and resize the browser window, it causes the <code>{{child.name}}</code> to render as the proper value, but only if I resize the browser.</p> <p><strong>UPDATE:</strong></p> <hr> <p>So I've gotten rid of the above filter, and replaced it with a very similar directive. This is my first attempt at creating a custom directive, so I'm fairly certain it could be done better, minus the obvious flaw that I cannot seem to work around currently. The directive is as follows:</p> <pre><code>.directive('truncate', function() { return { restrict: 'A', replace: true, template: '&lt;a class="entity-name" href="{{child.url}}" title="{{child.name}}"&gt;{{child.display}}&lt;/a&gt;', link: function(scope, element, attr) { var widthThreshold = $(element[0]).parent().parent().width() * 0.85; scope.$watch('child', function(val) { var elementWidth = $(element[0]).width(), characterCount = scope.child.name.length; while ($(element[0]).width() &gt; widthThreshold || characterCount &gt; 5) { characterCount--; scope.child.display = scope.child.name.substring(0, characterCount) + ' ...'; } }); } } }); </code></pre> <p>And I replace the partial to simply:</p> <pre><code>&lt;a truncate="child"&gt;&lt;/a&gt; </code></pre> <p>The differences in this as opposed to the filter are as follows (minus the obvious filter vs. directive):</p> <ol> <li>Replace <code>windowWidth</code> with <code>widthThreshold</code>, identifying the value by chaining jQuery's <code>.parent()</code> twice (essentially it's a more accurate value when getting the width of the parent (x2) element instead of the window).</li> <li>Added an additional key to <code>child</code> called <code>display</code>. This will be a truncated version of <code>child.name</code> that is used for display, instead of using jQuery's <code>.text()</code> and just rendering using a truncated <code>child.name</code>.</li> <li><code>truncPnt</code> becomes <code>characterCount</code> (trying to remember not to abbreviate variables)</li> </ol> <p>The problem now becomes that jQuery is freezing up the browser, until I kill the javascript (if prompted). Firefox may display it, Chrome has yet to not hang, and while I've yet to test in IE, I'd imagine worse than the former.</p> <p>What can be done to properly get the value of two parents above the main element in question, and truncate <code>child.display</code> so that it will not wrap/extend past the parent div?</p> <p><strong>UPDATE 2:</strong></p> <hr> <p>I decided to ditch the thought of primarily DOM-based calculations in favor of mathematics, accounting for the width of the parent div, font size, and a ratio of God knows what. I seriously plugged away at a formula until I got something that consistently gave similar results no matter the font size. Media queries do impact the font-size CSS of the string in question, so I needed to account for that or else have some drastic differences in the length of the truncated string between different font-size's:</p> <pre><code>.directive('truncate', function() { return { restrict: 'A', replace: true, // {{child.display}} will be a truncated copy of child.name template: '&lt;a class="entity-name" href="{{child.url}}" title="{{child.name}}"&gt;{{child.display}}&lt;/a&gt;', link: function(scope, element, attr) { var widthThreshold = $(element).parent().parent().width() * 0.85, // get the font-size without the 'px' at the end, what with media queries effecting font fontSize = $(element).css('font-size').substring(0, $(element).css('font-size').lastIndexOf('px')), // ... Don't ask... sizeRatio = 29760/20621, characterCount = Math.floor((widthThreshold / fontSize) * sizeRatio); scope.$watch('child', function(val) { // Truncate it and trim any possible trailing white-space var truncatedName = scope.child.name.substring(0, characterCount).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); // Make sure characterCount isn't &gt; the current length when accounting for the '...' if (characterCount &lt; scope.child.name.length + 3) { scope.child.display = truncatedName + '...'; } }); } } }); </code></pre> <p>Interestingly enough, I believe I came full circle back to Brandon Tilley's comment regarding modifying the DOM versus modifying a property in the scope. Now that I've changed it to modifying a property, it would probably better serve in a filter? What is typically the deciding factor for whether or not this sort of manipulation should be handled in a filter versus a directive?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload