Lazycoder

8Feb/056

adding innerText to Mozilla and other browsers

ComputerZen.com - Scott Hanselman's Weblog A JavaScript implementation of innerText (not innerHtml) for FireFox and non-IE browsers.

Earlier today Scott Hanselman posted a reg-ex based solution that would allow a Mozilla based browser to return the innerText of a given element. The innerText property is specific to Internet Explorers DOM. I hate, *HATE* calling static methods to do validation or emulate things that should be rightfully in the object I'm dealing with. This isn't to say that the solution he posted is either good or bad, but you end up having to call this funtion all over in your code. I thought there should be a way to use the W3C DOM level 3 textContent property to emulate the innerText property in Mozilla based browsers using ECMAScripts prototype functionality.. Well, I was half-right. There was a way to prototype the innerText property. But the textContent property wasn't quite the correct way to go. I found the solution here.

Here is a short example of the innerText prototype in action.

CODE:
  1. <script language="JavaScript">
  2. <!--
  3.    
  4.     if((typeof HTMLElement != 'undefined') && HTMLElement.prototype.__defineGetter__ != 'undefined'))
  5.     {
  6.         HTMLElement.prototype.__defineGetter__("innerText", function () {
  7.            var r = this.ownerDocument.createRange();
  8.            r.selectNodeContents(this);
  9.            return r.toString();
  10.         })
  11.     }
  12.  
  13.     function checkIt()
  14.     {
  15.         var hootie = document.getElementById("foo");
  16.         alert(hootie.innerText);
  17.     }
  18. //-->
  19. </script>
  20.  
  21. <body>
  22.     <form method=post action="">
  23.     <div id="foo">Hello World</div><br />
  24.     <input type="button" onClick="javascript:checkIt();"/>
  25.     </form>
  26. </body>

As an aside, I'm starting to love the W3C DOM level 3. Things like being able to define your own getters and setters for DOM objects is great for writing a cross-browser emulation layer.
edited to clean up the code a little bit

update, here is a setter implimentation taken from the site that appears to be down. Thanks Google cache!
The setter is really simpe. If you think about what innerText is doing, and realize that the innerHTML property is the same except that it has a few extra characters. What you have to do becomes pretty clear.

HTMLElement.prototype.__defineSetter__("innerText", function (sText) {
   this.innerHTML = sText.replace(/\&/g, "&").replace(//g, ">");
});
  • bg

    thats the getter, how about a setter?

    bg

  • Scott

    hmmm, funny you should mention that. I’m working on a control now that could use an innterHTML setter. I’ll work one out and post it.

  • http://electrobase.com Brian Cole

    clicked on solution, timed out. grrrrrrr

    man do i hate the internet. AND computers :-)

  • Pingback: Dino Esposito's WebLog

  • Pingback: GOOK’s Blog » Blog Archive » IE 이?? ?라? ???? innerText ????기

  • John Vance

    Bad browser detection! Bad! No cookie for you!

    Don’t check based on some capability you’re not going to use. You screw up other browsers that a) don’t have document.all and b) don’t have Mozilla-proprietary __defineGetter__.

    Try this instead:

    if (typeof HTMLElement != "undefined" &&
    typeof HTMLElement.prototype.__defineGetter__ != "undefined") {
    HTMLElement.prototype.__defineGetter__('innerText',
    function() {
    var tmp = this.innerHTML.replace(//gi, "\n");
    return tmp.replace(/]+>/g, "");
    }
    );
    HTMLElement.prototype.__defineSetter__('innerText',
    function(txtStr) {
    var parsedText = document.createTextNode(txtStr);
    this.innerHTML = "";
    this.appendChild( parsedText );
    }
    );
    }
    else if(typeof HTMLElement != "undefined" &&
    typeof document.body.innerText == "undefined"){
    alert("Warning: your browser is not supported");
    }

  • John Vance

    Hmmm – all my indenting was stripped from the above post.

  • Scott

    LOL, you’re absolutely correct John. I need to update this page. When I give a presentation on cross-browser Javascript, I make sure to tell people NOT to check browser versions, but to check functionality instead. In fact, I’ve made several other posts preaching that as well. Guess I need to change this post to practice what I preach!

    What’s missing from your code is the check to see if innerText is already supported on the given browser. :)

    As far as testing HTMLElement and __defineGetter, I believe they are both defined in DOM level 3. So if one is defined, the other should be as well. But you’re right, it’s best to check. Perhaps wrapping both checks into a page level browserFucntionality object. So your checks look something like this.

    var browserFunc;
    browserFunc.HTMLElement = (typeof HTMLElement != “undefined”);

    if(browserFunc.HTMLElement && browserFunc.defineGetter && !browserFunc.innerText)