To make a text “editable” I’ve written a function, which replaces the text with an input-element (step1) and later (onchange) replaces the text with the value of the input-element (step2)
this works except the following scenario: if the input-element is active (step1 of the precedure) and I click in the input-element, the text (in the input-element) is replaced with “undefined” and the function doesn’t work properly any more
<html>
<head>
<title>Test</title>
<script type="text/javascript">
<!--
// global variables for use in (out-of-function) listeners
var changeText_actual;
var changeText_parent;
function changeText(actual) {
// element representing a textNode
changeText_actual = actual;
// element containing the textNode
changeText_parent = actual.parentNode;
// create a new html-element to input text
var textfield = window.document.createElement("input"); {
textfield.setAttribute("type", "text");
// text in textNode
textfield.setAttribute("value", actual.data);
// listener for when user has finished input (e.g. by pressing return)
textfield.setAttribute("onchange",
// if inputText is not empty
"if(this.value && this.value.length > 0) {"
// fill textNode with inputText
+" changeText_actual.data = this.value;"
+"}"
// remove input-element and put textNode inplace
+"changeText_parent.replaceChild(changeText_actual, this);"
);
}
// remove textNode and put input-element inplace
changeText_parent.replaceChild(textfield, changeText_actual);
// select inputText for faster editing
textfield.select();
}
//-->
</script>
</head>
<body>
<table border="1"><tr>
<th>1. Text</th><th onclick="changeText(this.firstChild)">2. Text</th><th>3. Text</th>
</tr><tr>
<td>4. Text</td><td>5. Text</td><td>6. Text</td>
</tr></table>
</body>
</html>
I merely seek for an explanation than a solution, since I feel capable of working around this problem, if I know, where the “undefined” comes from (and where I can catch it)
1\ The first time you click on the <th> element, it’s first child is a text node. It’s data attribute is “2. Text”. So when you refer to this.firstChild, it is a text node.
2\ The function changeText will be called with a textnode as the parameter, so “actual” will be a text node.
You then change the text node to a textbox.
3\ When you click on the textbox, it’s parent’s onclick handler gets executed again (the onclick of the <th>), but this time, the this.firstChild is an <input> tag, so the function will be called with an input element as the parameter. the parameter “actual” will be an input element.
An input element has no attribute called data, so at the line
the actual.data is undefined.
That is the answer to your question but I feel the urge to clarify some things:
You can actually use textfield.onclick = function () { ….. } to write a function which is a much safer way.
Using the onchange for changing the textbox back to text is not always confortable (for example if you dont want to change anything), you should check if the element loses it’s focus too (blur).