views:

1842

answers:

10

I have a HTML file that has code similar to the following.

<table>
    <tr>
    <td id="MyCell">Hello  World</td>
    </tr>
</table>

I am using javascript like the following to get the value

document.getElementById(cell2.Element.id).innerText

This returns the text "Hello World" with only 1 space between hello and world. I MUST keep the same number of spaces, is there any way for that to be done?

I've tried using innerHTML, outerHTML and similar items, but I'm having no luck.

+6  A: 

HTML is white space insensititive which means your DOM is too. Would wrapping your "Hello World" in pre block work at all?

Nick
The actual situation is using a datagrid, and well, I don't think I can get it to do that. But you are 100% correct on the DOM rules. I was just hoping for a hack of sorts..
Mitchel Sellers
+6  A: 

In HTML,any spaces >1 are ignored, both in displaying text and in retrieving it via the DOM. The only guaranteed way to maintain spaces it to use a non-breaking space &nbsp;.

tj111
Also a good solution...
Nick
A: 

Just checked it and it looks like wrapping with the pre tag should do it.

Nick
+3  A: 

Just a tip, innerText only works in Internet Explorer, while innerHTML works in every browser... so, use innerHTML instead of innerText

Daniel Silveira
Thanks for the tip! We are on IE6 here and will be for a while, but that's good to know. Regardless, I get to re-write the code, this was enough to justify to mgmt that the code was unsafe! I hate legacy code...
Mitchel Sellers
A: 

The pre tag or white-space: pre in your CSS will treat all spaces as meaningful. This will also, however, turn newlines into line breaks, so be careful.

savetheclocktower
Too bad IE 7 seams to break this...
Rontologist
A: 

Edit: I am wrong, ignore me.

You can get a text node's nodeValue, which should correctly represent its whitespace.

Here is a function to recursively get the text within a given element (and it's library-safe, won't fail if you use something that modifies Array.prototype or whatever):

var textValue = function(element) {
    if(!element.hasOwnProperty('childNodes')) {
        return '';
    }
    var childNodes = element.childNodes, text = '', childNode;
    for(var i in childNodes) {
        if(childNodes.hasOwnProperty(i)) {
            childNode = childNodes[i];
            if(childNode.nodeType == 3) {
                text += childNode.nodeValue;
            } else {
                text += textValue(childNode);
            }
        }
    }
    return text;
};
eyelidlessness
I thought this too when I was going to write my answer. It still stripped the space in IE 7.
Rontologist
nodeValue is still a better option than innerHTML, since it counts < as one character instead of 4 (<)
Leo
A: 

Just an opinion here and not canonical advice, but you're headed for a world or hurt if you're trying to extract exact text values from the DOM using the inner/outer HTML/TEXT properties via Javascript. Different browsers are going to return slightly different values, based on how the browser "sees" the internal document.

If you can, I'd change the HTML you're rendering to include a hidden input, something like

<table>
    <tr>
    <td id="MyCell">Hello  World<input id="MyCell_VALUE" type="hidden" value="Hello  World" /></td>
    </tr>
</table>

And then grab your value in javascript something like

document.getElementById(cell2.Element.id+'_VALUE').value

The input tags were designed to hold values, and you'll be less likely to run into fidelity issues.

Also, it sounds like you're using a .NET control of some kind. It might be worth looking through the documentation (ha) or asking a slightly different question to see if the control offers an official client-side API of some kind.

Alan Storm
Oh I know how bad this is, I was just trying to see if there is a quick hack way to get around it. The control is an old ASP.NET 1.1 control that isn't even supported any more by the developer. The whole legacy code I inherited is crap....I'm going to re-write it the right way....
Mitchel Sellers
A: 

This is a bit hacky, but it works on my IE.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <title></title>
</head>
<body>
<div id="a">a  b</div>
<script>
var a = document.getElementById("a");
a.style.whiteSpace = "pre"
window.onload = function() {
    alert(a.firstChild.nodeValue.length) // should show 4
}
</script>
</body>
</html>

Some notes:

  • You must have a doctype.
  • You cannot query the DOM element before window.onload has fired
  • You should use element.nodeValue instead of innerHTML et al to avoid bugs when the text contains things like < > & "
  • You cannot reset whiteSpace once IE finishes rendering the page due to what I assume is an ugly bug
Leo
A: 

//This following trick preserves white-space in innerText in IE var cloned = element.cloneNode(true); var pre = document.createElement("pre"); pre.appendChild(cloned); var textContent = pre.textContent ? pre.textContent : pre.innerText; delete pre; delete cloned;

A: 

If someone could format my last post correctly it would look more readable. Sorry, I messed that one up. Basically the trick is create create a throwaway pre element, then append a copy of your node to that. Then you can get innerText or textContent depending on the browser.

All browsers except IE basically do the obvious thing correctly. IE requires this hack since it only preserves white-space in pre elements, and only when you access innerText.