Changing letters in boxes

J

Jukka K. Korpela

I wanted to accomplish something, and know javascript or jquery can do
the work, but my knowledge on both languages is too limited.

You don't need jQuery for a simple job like this. Using jQuery may
simplify coding a lot, but here probably the only thing it would be
useful for is simplifying the reference to a specific element. And
jQuery isn't really a language (at least not in the same sense as
JavaScript is a programming language) but a library that you may use in
addition to JavaScript, to ease coding.

Remove the jQuery-related script elements (the reference to the library
doesn't work anyway) and add the following:

<script>
function letters(a,b,c) {
document.getElementById('box').innerHTML =
'<td>' + a + '</td><td>' + b + '</td><td>' + c + '</td>' ;
}
</script>

Change the <tr> tag for the table to <tr id=box>. (Here and before "box"
is just an identifier; choose another one if you can find a more
self-documenting name.)

Add onclick attributes to the <input> element to make them as follows:

box #1: <input type="text" value='x y z' size='10'
onclick="letters('x','y','z')" /><br />
box #2: <input type="text" value='a b c' size='10'
onclick="letters('a','b','c')" /><br />
box #3: <input type="text" size='10' onclick="letters('','','')" />

This way, the entire <tr> element is changed at the same time as
requested (though in practice, just replacing the <td> contents in
sequence would be just as good, unless there is a real risk of
intervening interrupts).

Note that clicking on the last box makes the letters disappear entirely,
i.e. the contents of each <td> element becomes empty, and this affects
the layout - the cells shrink. (They are still 10px wide and high due to
the padding you set.) If this is not desirable, there are varyings
things you can do, depending on the exact desired appearance. For
example, you could use '\xa0' (standing for no-break space) instead of
'' to make the cells preserve height (though not width) when cleared.
 
F

fulio pen

You don't need jQuery for a simple job like this. Using jQuery may
simplify coding a lot, but here probably the only thing it would be
useful for is simplifying the reference to a specific element. And
jQuery isn't really a language (at least not in the same sense as
JavaScript is a programming language) but a library that you may use in
addition to JavaScript, to ease coding.



Remove the jQuery-related script elements (the reference to the library
doesn't work anyway) and add the following:

<script>
function letters(a,b,c) {
   document.getElementById('box').innerHTML =
     '<td>' + a + '</td><td>' + b + '</td><td>' + c +  '</td>' ;
  }
</script>

Change the <tr> tag for the table to <tr id=box>. (Here and before "box"
is just an identifier; choose another one if you can find a more
self-documenting name.)

Add onclick attributes to the <input> element to make them as follows:

box #1: <input type="text" value='x y z' size='10'
onclick="letters('x','y','z')" /><br />
box #2: <input type="text" value='a b c' size='10'
onclick="letters('a','b','c')" /><br />
box #3: <input type="text" size='10' onclick="letters('','','')" />

This way, the entire <tr> element is changed at the same time as
requested (though in practice, just replacing the <td> contents in
sequence would be just as good, unless there is a real risk of
intervening interrupts).

Note that clicking on the last box makes the letters disappear entirely,
i.e. the contents of each <td> element becomes empty, and this affects
the layout - the cells shrink. (They are still 10px wide and high due to
the padding you set.) If this is not desirable, there are varyings
things you can do, depending on the exact desired appearance. For
example, you could use '\xa0' (standing for no-break space) instead of
'' to make the cells preserve height (though not width) when cleared.

Thanks a lot. Will change accordingly immediately, and come back with
the changed page.

fulio pen
 
F

fulio pen

You don't need jQuery for a simple job like this. Using jQuery may
simplify coding a lot, but here probably the only thing it would be
useful for is simplifying the reference to a specific element. And
jQuery isn't really a language (at least not in the same sense as
JavaScript is a programming language) but a library that you may use in
addition to JavaScript, to ease coding.



Remove the jQuery-related script elements (the reference to the library
doesn't work anyway) and add the following:

<script>
function letters(a,b,c) {
   document.getElementById('box').innerHTML =
     '<td>' + a + '</td><td>' + b + '</td><td>' + c +  '</td>' ;
  }
</script>

Change the <tr> tag for the table to <tr id=box>. (Here and before "box"
is just an identifier; choose another one if you can find a more
self-documenting name.)

Add onclick attributes to the <input> element to make them as follows:

box #1: <input type="text" value='x y z' size='10'
onclick="letters('x','y','z')" /><br />
box #2: <input type="text" value='a b c' size='10'
onclick="letters('a','b','c')" /><br />
box #3: <input type="text" size='10' onclick="letters('','','')" />

This way, the entire <tr> element is changed at the same time as
requested (though in practice, just replacing the <td> contents in
sequence would be just as good, unless there is a real risk of
intervening interrupts).

Note that clicking on the last box makes the letters disappear entirely,
i.e. the contents of each <td> element becomes empty, and this affects
the layout - the cells shrink. (They are still 10px wide and high due to
the padding you set.) If this is not desirable, there are varyings
things you can do, depending on the exact desired appearance. For
example, you could use '\xa0' (standing for no-break space) instead of
'' to make the cells preserve height (though not width) when cleared.

Hi, Yucca:

Thanks for your help. I changed the code by taking your advice. The
new page is as follows:

http://www.pinyinology.com/js_learning/letters.html

In above page, I like to change the cursor to default in the boxes.
Now it is a vertical bar called text. I tried to change it, but failed
all efforts. I may have more questions, but have to modify the page
to present them. Thanks again.

fulio pen
 
T

Thomas 'PointedEars' Lahn

Jukka said:
<script>
function letters(a,b,c) {
document.getElementById('box').innerHTML =
'<td>' + a + '</td><td>' + b + '</td><td>' + c + '</td>' ;
}
</script>

Change the <tr> tag for the table to <tr id=box>. (Here and before "box"
is just an identifier; choose another one if you can find a more
self-documenting name.)

Unreliable. Especially MSHTML (the layout engine that Internet Explorer
uses) is prone to errors with `innerHTML' accesses in table structures.

A safer approach is to remove all cells of the row except one, then replace
the content of the first cell and add more cells:

var tr = document.getElementById("box");
var firstChild = tr.firstChild;
while (tr.lastChild != firstChild)
{
tr.removeNode(tr.lastChild);
}

tr.cells[0].innerHTML = a;

var td1 = document.createElement("td");
td1.innerHTML = b;

/* or td1.cloneNode(false) */
var td2 = document.createElement("td");
td2.innerHTML = c;

tr.appendChild(td1);
tr.appendChild(td2);

(It suffices here to add text nodes to the cells, or replace their values if
existing, instead of using the proprietary and error-prone `innerHTML'
property. This can be accomplished using the `textContent' property of DOM
Level 3 Core or the document.createTextNode(…) and appendChild(…) methods of
DOM Level 2+ Core.)

Another possibility is to rewrite the entire table with `innerHTML'.
Quirksmode.org results have shown that this can be much more efficient than
the standards-compliant DOM approach. But probably not in this case.
Add onclick attributes to the <input> element to make them as follows:

box #1: <input type="text" value='x y z' size='10'
onclick="letters('x','y','z')" /><br />
box #2: <input type="text" value='a b c' size='10'
onclick="letters('a','b','c')" /><br />
box #3: <input type="text" size='10' onclick="letters('','','')" />

Since the value of the control can be used to construct the argument list
for the letters() method, and the `click' event bubbles universally, it
might not be necessary that each `input' element has an `onclick' attribute
specified. For example:

<script type="text/javascript">// <![CDATA[
function clickHandler(e)
{
var t = e.target || e.srcElement;
if (t)
{
if (t.nodeType == 3)
{
/* if a text node */
t = t.parentNode;
}

if (t.tagName.toUpperCase() == "INPUT")
{
letters.apply(null, t.value.split(" "));
}
}
}
// ]]></script>

<… onclick="if (typeof event != "undefined") clickHandler(event)" …>
<input type="text" value='x y z' size='10' /><br />
<input type="text" value='a b c' size='10' /><br />
<input type="text" size='10' value=' ' />
</…>

Usability, in particular keyboard navigation, might be better served by
listening to the not universally bubbling `focus' event instead, though.
For that matter, formatting should not be achieved using the `br' element,
but a semantic element, for example `label' elements that are parent
elements of their `input' elements.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
<… onclick="if (typeof event != "undefined") clickHandler(event)" …>

That has to be

<… onclick="if (typeof event != 'undefined') clickHandler(event)" …>

or

<input type="text" value='x y z' size='10' /><br />
<input type="text" value='a b c' size='10' /><br />
<input type="text" size='10' value=' ' />
</…>

[…]


PointedEars
 
J

Jukka K. Korpela

http://www.pinyinology.com/js_learning/letters.html

In above page, I like to change the cursor to default in the boxes.
Now it is a vertical bar called text.

Setting the cursor is a CSS issue, not JavaScript (though you can set
the element property corresponding to the CSS property via JavaScript,
but there's no reason to do so if you want the setting to take effect
independently of the state of the page).

So please check
http://www.w3.org/TR/CSS21/ui.html#propdef-cursor
Note that an <input type=text> element typically has cursor: text set in
the browser stylesheet, so it won't inherit the property from its
ancestor. To set the cursor on <input> elements, use e.g.
input { cursor: default; }
in your stylesheet.
 
F

fulio pen

Setting the cursor is a CSS issue, not JavaScript (though you can set
the element property corresponding to the CSS property via JavaScript,
but there's no reason to do so if you want the setting to take effect
independently of the state of the page).

So please checkhttp://www.w3.org/TR/CSS21/ui.html#propdef-cursor
Note that an <input type=text> element typically has cursor: text set in
the browser stylesheet, so it won't inherit the property from its
ancestor. To set the cursor on <input> elements, use e.g.
input { cursor: default; }
in your stylesheet.

Hi, Jukka:

Thanks a lot. The "input { cursor: default; }" has been inserted to
the style section. Now the cursor is the default arrow:

http://www.pinyinology.com/js_learning/letters.html

Other people have also helped me. I thank them all very much, and will
study their suggestions carefully to modify the code.

Thank you all for your help.

fulio pen
 
M

Matt McDonald

Unreliable. Especially MSHTML (the layout engine that Internet Explorer
uses) is prone to errors with `innerHTML' accesses in table structures.

A safer approach is to remove all cells of the row except one, then replace
the content of the first cell and add more cells...

Agreed. Given the Table API that the DOM provides, usage of innerHTML
here is erroneous, especially in IE. There's also, of course,
createElement + appendChild if desired.

I wrote an article earlier today on this topic, except utilizing the DOM
Table API (insertCell + deleteCell):

http://www.fortybelow.ca/hosted/comp-lang-javascript/table-cell-replacement/

Comments are welcome.
 
T

Thomas 'PointedEars' Lahn

Matt said:
Agreed. Given the Table API that the DOM provides, usage of innerHTML
here is erroneous, especially in IE. There's also, of course,
createElement + appendChild if desired.

I wrote an article earlier today on this topic, except utilizing the DOM
Table API (insertCell + deleteCell):

http://www.fortybelow.ca/hosted/comp-lang-javascript/table-cell- replacement/

Comments are welcome.

One problem which what you dubbed "DOM Table Cell API" (there really is no
official name for that part of the W3C DOM Level 2 HTML Specification) is
that the W3C DOM API Specification and the MSHTML DOM API definition
disagree (again, cf. HTMLSelectElement::add() [1]) with regard to the
meaning of the method's arguments and its return value:

Both support the value -1 to append a new cell; but while the standards-
compliant implementation requires the number of existing cells to be passed
for an alternative of that (tr.cells.length), MSHTML is at least documented
to require tr.cells.length - 1. Also, while the standards-compliant
implementation is supposed to throw DOMException INDEX_SIZE_ERR on error,
MSHTML is at least documented to throw no exception at all then, but to
return "null" instead (which, for the ECMAScript binding, is the `null'
value of the JScript implementation of the Null type). [2]

The same problem exists with
HTMLTableElement/HTMLTableSectionElement::insertRow(). [3]

Those differences suggest the possibility of other differences between
standards-compliant and other implementations than the MSHTML DOM in this
area. Therefore, I have intentionally used DOM Level 2+ Core methods in my
example – for which I am not aware of such quirks – and made no mention of
that "DOM Table Cell API".


PointedEars
___________
[1] <http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-14493106>
<http://msdn.microsoft.com/en-us/library/ms535921(VS.85).aspx>
[2] <http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-68927016>
<http://msdn.microsoft.com/en-us/library/ms536455(VS.85).aspx>
[3] <http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-93995626>
<http://msdn.microsoft.com/en-us/library/ms536457(VS.85).aspx>
 
R

RobG

Unreliable.  Especially MSHTML (the layout engine that Internet Explorer
uses) is prone to errors with `innerHTML' accesses in table structures.

Yes. MS documentation explicitly says not to use innerHTML to modify
tables[1].
A safer approach is to remove all cells of the row except one, then replace
the content of the first cell and add more cells:

  var tr = document.getElementById("box");
  var firstChild = tr.firstChild;
  while (tr.lastChild != firstChild)
  {
    tr.removeNode(tr.lastChild);
  }

  tr.cells[0].innerHTML = a;

You seem to be assuming here that the firstChild of the tr will be a
cell (TD or TH), when it may be a text node:

<table>
<tr onclick="alert(this.firstChild);">
<td>foo
</table>

The above shows "3" for the text node following the TR in Firefox,
Opera and Chrome, or "1" for the element node in IE 8 (which seems to
omit the text node).

To get the first cell, better to be explicit:

var firstCell = tr.cells[0];

An alternative is getElementsByTagName('td')[0], but the cells can be
TH or TD, using the cells collection deals with both.

[...]
When all you know is jQuery, every problem looks $olvable.

<grin> is that one of yours?

1. http://msdn.microsoft.com/en-us/library/ms533897(v=VS.85).aspx
 
J

Jukka K. Korpela

MS documentation explicitly says not to use innerHTML to modify
tables[1].

Then I would recommend just putting id attributes on each <td> and
changing the cell contents. Any practical risk of making the cell update
operation divisible that way must be ignorable when compared with the
risks caused by added complexity of code.

But if an indivisible operation is really needed, then the simplest
approach that avoids the IE bug is probably something like this:

function addCell(row,data) {
var cell = document.createElement('td');
cell.innerHTML = data;
row.appendChild(cell);
}
function letters(a,b,c) {
var boxId = 'box';
var box = document.getElementById(boxId);
var newRow = document.createElement('tr');
newRow.id = boxId;
addCell(newRow,a);
addCell(newRow,b);
addCell(newRow,c);
box.parentNode.replaceChild(newRow,box);
}
An alternative is getElementsByTagName('td')[0], but the cells can be
TH or TD, using the cells collection deals with both.

No, all the three cells are <td> elements. If the real intent is to
create something easily modifiable and extensible, then you might worry
about the optimal way of retrieving all cells, or all data cells, in a
table row, and looping through them, but the problem posed was specific
and simple.
 
T

Thomas 'PointedEars' Lahn

RobG said:
Thomas said:
A safer approach is to remove all cells of the row except one, then
replace the content of the first cell and add more cells:

var tr = document.getElementById("box");
var firstChild = tr.firstChild;
while (tr.lastChild != firstChild)
{
tr.removeNode(tr.lastChild);
}

tr.cells[0].innerHTML = a;

You seem to be assuming here that the firstChild of the tr will be a
cell (TD or TH), when it may be a text node:
ACK

[…]
To get the first cell, better to be explicit:

var firstCell = tr.cells[0];
ACK

An alternative is getElementsByTagName('td')[0], but the cells can be
TH or TD, using the cells collection deals with both.

A viable alternative alternative are the `firstElementChild' and
`lastElementCild' properties if they are available.
[...]
When all you know is jQuery, every problem looks $olvable.

<grin> is that one of yours?

Yes :) It occurred to me when reading from John-David Dalton (@jdalton, on
Twitter) that the jQuery Standards Group (sic!) he recently joined is going
to suggest adding Array methods to NodeLists because they see so much
[].forEach.call(hostObject) etc. these days. Of course, my answer was – the
fact aside that this would make the DOM API language-dependent – that in a
well-developed Web application you seldom ever need [].….call(hostObject) to
begin with.

Thanks a lot, for some reason I had to rely on long-forgotten table-
scripting experience with MSHTML and third-party information regarding this.
It is acceptable to see this quirk being officially documented at last.

In fact, when you read on to [1] they are saying in the "Creating and
Manipulating Tables" section that the `innerHTML' and `innerText' properties
are *read-only* for `table' and `tr' objects, which makes kind of
Microsoftish sense considering the quirks and their proprietary table object
model. This would mean it is not only unwise to use `innerHTML' there, but
that it was functionally impossible.


PointedEars
___________
[1] <http://msdn.microsoft.com/en-us/library/ms532998(VS.85).aspx>
 
M

Matt McDonald

One problem which what you dubbed "DOM Table Cell API" (there really is no
official name for that part of the W3C DOM Level 2 HTML Specification) is
that the W3C DOM API Specification and the MSHTML DOM API definition
disagree (again, cf. HTMLSelectElement::add() [1]) with regard to the
meaning of the method's arguments and its return value:

Right. That was a silly typo ("Table Cell" over "Table"). I've amended
the title along with any reference to any "API" short of the DOM itself.
Both support the value -1 to append a new cell; but while the standards-
compliant implementation requires the number of existing cells to be passed
for an alternative of that (tr.cells.length), MSHTML is at least documented
to require tr.cells.length - 1. Also, while the standards-compliant
implementation is supposed to throw DOMException INDEX_SIZE_ERR on error,
MSHTML is at least documented to throw no exception at all then, but to
return "null" instead (which, for the ECMAScript binding, is the `null'
value of the JScript implementation of the Null type). [2]

Noted in both cases. Thanks.
The same problem exists with
HTMLTableElement/HTMLTableSectionElement::insertRow(). [3]

Those differences suggest the possibility of other differences between
standards-compliant and other implementations than the MSHTML DOM in this
area. Therefore, I have intentionally used DOM Level 2+ Core methods in my
example – for which I am not aware of such quirks – and made no mention of
that "DOM Table Cell API".

Ah, I see. Still, it's a powerful set of methods/properties that tend to
get overlooked.

Regarding your double colon notation :):), am I to infer those
properties/methods are static? I've been unable to locate anything
utilizing that notation regarding the DOM beyond your posts.

Finally, I've spent most of today cleaning up the article and making it
easier to parse through. I'd like to thank you for reviewing it and
being very thorough (as always). Will you mind if I attribute you in the
footnotes?

PS: Your suggestion previously to stick to table cell modification
instead of a complete overhaul of the row led me to fix a reflow bug in
IE:Mac. Thanks a bunch. :)
 
T

Thomas 'PointedEars' Lahn

Matt said:
The same problem exists with
HTMLTableElement/HTMLTableSectionElement::insertRow(). [3]

Those differences suggest the possibility of other differences between
standards-compliant and other implementations than the MSHTML DOM in this
area. Therefore, I have intentionally used DOM Level 2+ Core methods in
my example – for which I am not aware of such quirks – and made no
mention of that "DOM Table Cell API".

Ah, I see. Still, it's a powerful set of methods/properties that tend to
get overlooked.
ACK

Regarding your double colon notation :):), am I to infer those
properties/methods are static? I've been unable to locate anything
utilizing that notation regarding the DOM beyond your posts.

ECMAScript Ed. 1 to 3, and 5 do not specify class-based inheritance and have
no notion of static methods as they are defined in class-based OOP.
Apparently we (the participants of this newsgroup that I am aware of) use
the shortcut "static" (I try to use it in quotes in discussions, to be sure)
to talk about a property that is a property of a constructor (like
Object.defineProperty) or is otherwise not implicitly inherited by other
objects (like Math.max).

`::' notation is my way of referring (unambiguously, or so it seemed) to the
interface specification (formally given in OMG IDL) instead of some
ECMAScript object or an object available through ECMAScript language binding
(like Node.ELEMENT_NODE in some DOM implementations). Keep in mind that the
W3C DOM is a *language-independent* API, where language binding is specified
for some programming languages, including ECMAScript implementations:

<http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html>
(You can find similar sections in the other module specifications.)

So when I wrote "HTMLSelectElement::add()", read it as if I had written "the
add() method of objects implementing the HTMLSelectElement interface of W3C
DOM Level 2 HTML". (Easier, yes?)
Finally, I've spent most of today cleaning up the article and making it
easier to parse through. I'd like to thank you for reviewing it and
being very thorough (as always). Will you mind if I attribute you in the
footnotes?

I would not, but I have not reviewed it yet (except perhaps, by
coincidence). Perhaps later this week. You better remind me.
PS: Your suggestion previously to stick to table cell modification
instead of a complete overhaul of the row led me to fix a reflow bug in
IE:Mac. Thanks a bunch. :)

You are welcome.


Regards,

PointedEars
 
A

Andreas Bergmaier

Andrew said:
Shouldn't [that] be on two lines, thus:
// ]]>
</script>
?

Doesn't the leading "//" comment out the entire line?

Yes, but that doesn't matter the HTML Parser. The (X)HTML(soup)-Parser
just looks for the end of the CDATA-section (if it knows about CDATA -
else it looks for the end of the <script>-tag), and then might send its
content to the script engine.

Bergi
 
T

Thomas 'PointedEars' Lahn

Andreas said:
Andrew said:
Shouldn't [that] be on two lines, thus:
// ]]>
</script>
?

Doesn't the leading "//" comment out the entire line?

Yes, but that doesn't matter the HTML Parser. The (X)HTML(soup)-Parser
just looks for the end of the CDATA-section (if it knows about CDATA -
else it looks for the end of the <script>-tag), and then might send its
content to the script engine.

That CDATA declaration is for real X(HT)ML parsers only. An HTML parser
would ignore it since the content model of the HTML SCRIPT element is CDATA
already (hence the single-line comments for the script engine); it would
look for `</' instead (which is why you should escape ETAGO delimiters – </
– regardless in XHTML `script' elements). A tagsoup parser would not care
at all, it would probably look for `</script>' only (which is also why you
get used to escaping unwanted ETAGOs there).


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top