Solving the Firefox Ellipsis Problem

by

On a recent project for a client, I was asked to make the CSS style “text-overflow: ellipsis” work on FireFox browsers, which has never supported this style. This style basically truncates text and adds an ellipsis (…) when the length of the text overflows the container. Supposedly FireFox 7.0 will correctly this issue, but I’ll believe it when I see it.

While there are several good blog posts out there to help out, none of them handle the resizing of the window/text container. That gets tricky because you need to persist the original text so you can make the text longer or shorter as needed during resizing.

Anyway, I thought I’d share my code here to help out any other poor souls stuck with this problem. Here it is (I am assuming you use jQuery; who doesn’t? :-)):

var ellipsisPages = (function() {

  return {
    init: function() {
      ellipsisPages.drawEllipses();
    },

    drawEllipses: function() {
      /**
       * Trigger FF ellipsis if text overflow isn’t supported
and it’s a Gecko based browser

       */
      var textOverflowSupported =
typeof document.createElement(“span”).style.textOverflow === “string”;

      if (navigator.product === “Gecko” && !textOverflowSupported) {

        if($(‘.ffEllipsis’).length > 0){

          $(‘.ffEllipsis’).each(function(idx, item) {

            if ($(item).attr(‘data’) == undefined) {
                            $(item).attr(‘data’, item.innerHTML)
                        }

              // Determine the text width
              function getTextWidth(text) {

                 var lDiv = document.createElement(‘lDiv’);
                 document.body.appendChild(lDiv);
                 lDiv.style.fontSize = item.style.fontSize;
                 lDiv.style.fontFamily = item.style.fontFamily;
                 lDiv.style.position = “absolute”;
                 lDiv.style.left = -1000;
                 lDiv.style.top = -1000;

                 lDiv.innerHTML = text;

                 var textWidth = lDiv.clientWidth;
                 document.body.removeChild(lDiv);
                 lDiv = null;
                 return textWidth;
               }

               var text = $(item).attr(‘data’);
               var origTextLength = text.length;
               var tw = getTextWidth(text);
               var parentWidth = item.clientWidth;

               // TODO: perhaps recurse up to a width?
               if (parentWidth == 0) {

                 parentWidth = item.parentNode.clientWidth;
               }

               // Shrink text to fit; TODO: optimize this algorithm
               while (parentWidth > 20 && tw > parentWidth – 20) {

                 text = text.substring(0, text.length – 1);
                 tw = getTextWidth(text);
               }

               if (origTextLength > text.length) {

                 var lDiv = null;
                 // See if we already added our custom element
                 for (var node in item.childNodes) {

                   if (node.localName == ‘ldiv’) {
                     lDiv = node;
                       break;
                   }
                 }

                 // Create an inner element if we haven’t already
                 if (lDiv == null) {

                   while(item.childNodes[0])
                     item.removeChild(item.childNodes[0]);

                   lDiv = document.createElement(‘ldiv’);
                   lDiv.style.fontSize = item.style.fontSize;
                   lDiv.style.fontFamily = item.style.fontFamily;
                   item.appendChild(lDiv);
                 }

                 lDiv.innerHTML = text + “…”;
              }
           });
         }
       }
     }
  }
})();

$(document).ready(function(){
  // Call on a window resize
  $(window).resize(ellipsisPages.drawEllipses());
});

Note the area you want ‘ellipsified’ needs to have the CSS class ‘ffEllipsis’ assigned (and the JavaScript included, of course) and you are off and running! One note: this can be a performance drag on the page if there are a lot of elements needing ellipses. Use with caution.

Enjoy!

 

 

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *