Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #17400 > unrolled thread

Problem w/ creating dynamic TR and its TDs

Started byjustaguy <lichunshen84@gmail.com>
First post2012-12-01 15:17 -0800
Last post2012-12-02 19:39 +0100
Articles 11 — 3 participants

Back to article view | Back to comp.lang.javascript


Contents

  Problem w/ creating dynamic TR and its TDs justaguy <lichunshen84@gmail.com> - 2012-12-01 15:17 -0800
    Re: Problem w/ creating dynamic TR and its TDs Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-12-02 00:34 +0100
      Re: Problem w/ creating dynamic TR and its TDs justaguy <lichunshen84@gmail.com> - 2012-12-01 17:06 -0800
      Re: Problem w/ creating dynamic TR and its TDs Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-12-02 03:46 +0100
        Re: Problem w/ creating dynamic TR and its TDs justaguy <lichunshen84@gmail.com> - 2012-12-01 19:27 -0800
          Re: Problem w/ creating dynamic TR and its TDs Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-12-03 22:53 +0100
        Re: Problem w/ creating dynamic TR and its TDs Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-12-02 08:43 +0100
          Re: Problem w/ creating dynamic TR and its TDs Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-12-02 16:11 +0100
            Re: Problem w/ creating dynamic TR and its TDs Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2012-12-02 18:48 +0100
              Re: Problem w/ creating dynamic TR and its TDs Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-12-02 19:35 +0100
                Re: Problem w/ creating dynamic TR and its TDs Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2012-12-02 19:39 +0100

#17400 — Problem w/ creating dynamic TR and its TDs

Fromjustaguy <lichunshen84@gmail.com>
Date2012-12-01 15:17 -0800
SubjectProblem w/ creating dynamic TR and its TDs
Message-ID<e4c1bc98-b6a5-4142-a7a7-3fff318a7057@l12g2000vbj.googlegroups.com>
Hi,

I've done such dynamic creation of TR and its TDs a while ago... but
runs into problem.
The thought is, if I have a current TR with ID of "row1", then the
following code should be able to create a new TR and its TDs and
append them to the "row1" Row.

HTML:
<table>
<tr id="row1">
  <td><input type="text" id="myname" name="myname"><td>
  <td><input type="text" id="mydesc" name="mydesc"><td>
</tr>
</table>

Javascript:
// find or define current row
var currentRow = "row1">

// create new Row and Cells
var cnt = 1;
var newrow = document.createElement("tr");
var cell = document.createElement("td");
var cellText = document.createTextNode("<input type=text
name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
cell.appendChild(cellText);
newrow.appendChild(cell);

// now append the new Row and its Cells to current row
currentRow.appendChild(newrow);

Question, that line of
var cellText = document.createTextNode("<input type=text
name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
is wrong, that is, it's a text node, not an input node, and I don't
think there's something like createInputNode something, so, how do we
do it?

Thanks in advance.

[toc] | [next] | [standalone]


#17401

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-12-02 00:34 +0100
Message-ID<k9e45v$d6v$1@speranza.aioe.org>
In reply to#17400
W dniu 2012-12-02 00:17, justaguy pisze:
> Hi,
>
> I've done such dynamic creation of TR and its TDs a while ago... but
> runs into problem.
> The thought is, if I have a current TR with ID of "row1", then the
> following code should be able to create a new TR and its TDs and
> append them to the "row1" Row.
>
> HTML:
> <table>
> <tr id="row1">
>    <td><input type="text" id="myname" name="myname"><td>
>    <td><input type="text" id="mydesc" name="mydesc"><td>
> </tr>
> </table>
>
> Javascript:
> // find or define current row
> var currentRow = "row1">
>
> // create new Row and Cells
> var cnt = 1;
> var newrow = document.createElement("tr");
> var cell = document.createElement("td");
> var cellText = document.createTextNode("<input type=text
> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> cell.appendChild(cellText);
> newrow.appendChild(cell);
>
> // now append the new Row and its Cells to current row
> currentRow.appendChild(newrow);
>
> Question, that line of
> var cellText = document.createTextNode("<input type=text
> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> is wrong, that is, it's a text node, not an input node, and I don't
> think there's something like createInputNode something, so, how do we
> do it?

You can use something like this as a workaround for old IE and problems 
with "input type name":

elm - node name
attributes - object with atttributes

var createElement = function(elm, attributes){
     var div = document.createElement("div"),
         element = document.createElement(elm);

     for(var p in attributes){
       element[p]= attributes[p];
     }

     div.appendChild(element);
     return div.firstChild;
};

This is just an example and probably code could be more improved.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#17403

Fromjustaguy <lichunshen84@gmail.com>
Date2012-12-01 17:06 -0800
Message-ID<4d004cfe-16ec-4241-8a85-ca3c02d040d2@m13g2000vbd.googlegroups.com>
In reply to#17401
On Dec 1, 6:34 pm, Cezary Tomczyk <cezary.tomc...@gmail.com> wrote:
> W dniu 2012-12-02 00:17, justaguy pisze:
>
>
>
>
>
>
>
>
>
> > Hi,
>
> > I've done such dynamic creation of TR and its TDs a while ago... but
> > runs into problem.
> > The thought is, if I have a current TR with ID of "row1", then the
> > following code should be able to create a new TR and its TDs and
> > append them to the "row1" Row.
>
> > HTML:
> > <table>
> > <tr id="row1">
> >    <td><input type="text" id="myname" name="myname"><td>
> >    <td><input type="text" id="mydesc" name="mydesc"><td>
> > </tr>
> > </table>
>
> > Javascript:
> > // find or define current row
> > var currentRow = "row1">
>
> > // create new Row and Cells
> > var cnt = 1;
> > var newrow = document.createElement("tr");
> > var cell = document.createElement("td");
> > var cellText = document.createTextNode("<input type=text
> > name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> > cell.appendChild(cellText);
> > newrow.appendChild(cell);
>
> > // now append the new Row and its Cells to current row
> > currentRow.appendChild(newrow);
>
> > Question, that line of
> > var cellText = document.createTextNode("<input type=text
> > name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> > is wrong, that is, it's a text node, not an input node, and I don't
> > think there's something like createInputNode something, so, how do we
> > do it?
>
> You can use something like this as a workaround for old IE and problems
> with "input type name":
>
> elm - node name
> attributes - object with atttributes
>
> var createElement = function(elm, attributes){
>      var div = document.createElement("div"),
>          element = document.createElement(elm);
>
>      for(var p in attributes){
>        element[p]= attributes[p];
>      }
>
>      div.appendChild(element);
>      return div.firstChild;
>
> };
>
> This is just an example and probably code could be more improved.
>
> --
> Cezary Tomczykhttp://www.ctomczyk.pl/

Hi, thanks for the idea, but we must to create a new element inside
the existing HTML table.
I just learned the createElement('input') syntax can do the job.
For instance,
 var cell = document.createElement("td");
 var cellText = document.createElement('input');

but now the trouble is with associating a class to it, the following
syntax appears to be correct,
however, it's ineffective.
cellText.setAttribute('class','autocomplete');  //  major non-IE
browsers
cellText.setAttribute('className','autocomplete'); // IE browser

Also, another problem I have is, the newly added TR shows up right
next to the existing TR,
instead of in next row.  How come?

Thanks.

[toc] | [prev] | [next] | [standalone]


#17404

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-12-02 03:46 +0100
Message-ID<5462881.fXVs31Ce0e@PointedEars.de>
In reply to#17401
Cezary Tomczyk wrote:

> W dniu 2012-12-02 00:17, justaguy pisze:
>> I've done such dynamic creation of TR and its TDs a while ago... but
>> runs into problem.
>> The thought is, if I have a current TR with ID of "row1", then the
>> following code should be able to create a new TR and its TDs and
>> append them to the "row1" Row.
>>
>> HTML:
>> <table>
>> <tr id="row1">
>>    <td><input type="text" id="myname" name="myname"><td>
>>    <td><input type="text" id="mydesc" name="mydesc"><td>
>> </tr>
>> </table>
>>
>> Javascript:
>> // find or define current row
>> var currentRow = "row1">
>>
>> // create new Row and Cells
>> var cnt = 1;
>> var newrow = document.createElement("tr");
>> var cell = document.createElement("td");
>> var cellText = document.createTextNode("<input type=text
>> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
>> cell.appendChild(cellText);
>> newrow.appendChild(cell);
>>
>> // now append the new Row and its Cells to current row
>> currentRow.appendChild(newrow);
>>
>> Question, that line of
>> var cellText = document.createTextNode("<input type=text
>> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
>> is wrong, that is, it's a text node, not an input node, and I don't
>> think there's something like createInputNode something, so, how do we
>> do it?
> 
> You can use something like this as a workaround for old IE and problems
> with "input type name":

There is no such problem.  You are confusing this with changing the value of 
the `type' property of an `input' element object after the corresponding 
element has been appended.
 
> elm - node name
> attributes - object with atttributes
> 
> var createElement = function(elm, attributes){
>      var div = document.createElement("div"),

Unnecessary; potentially harmful here (a `div' element in a `td' element).

>          element = document.createElement(elm);

OK.
 
>      for(var p in attributes){

Iterates over enumerable properties of `attributes'.  Better:

  for (var keys = Object.keys(attributes), i = 0, len = keys.length;
       i < len;
       ++i)

or pre-ES 5.1 variants thereof.  See also jsx.object.getKeys().

>        element[p]= attributes[p];

Fails to account for the mapping of attribute names that are reserved words 
to special attribute properties (like "for" → "htmlFor"), and of the `style' 
attribute.  See also jsx.dom.setAttr().

>      }
> 
>      div.appendChild(element);
>      return div.firstChild;

I beg your pardon?  What exactly are you creating the `div' element for if 
you are not returning a reference to it?  Mystical incantation?

> };
> 
> This is just an example and probably code could be more improved.

It is a solution looking for a problem while creating more problems than it 
fails to solve.   The correct way to address the problem actually posed by 
the question (as opposed to your answer) is:

  var input = document.createElement("input");
  input.name = "partnumber" + cnt;
  input.id = "partnumber" + cnt;
  input.className = "autocomplete";
  cell.appendChild(input);


PointedEars
-- 
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

[toc] | [prev] | [next] | [standalone]


#17405

Fromjustaguy <lichunshen84@gmail.com>
Date2012-12-01 19:27 -0800
Message-ID<17c6ca39-08f8-41b7-9d84-b1862cd6bd39@t5g2000vba.googlegroups.com>
In reply to#17404
On Dec 1, 9:46 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
> Cezary Tomczyk wrote:
> > W dniu 2012-12-02 00:17, justaguy pisze:
> >> I've done such dynamic creation of TR and its TDs a while ago... but
> >> runs into problem.
> >> The thought is, if I have a current TR with ID of "row1", then the
> >> following code should be able to create a new TR and its TDs and
> >> append them to the "row1" Row.
>
> >> HTML:
> >> <table>
> >> <tr id="row1">
> >>    <td><input type="text" id="myname" name="myname"><td>
> >>    <td><input type="text" id="mydesc" name="mydesc"><td>
> >> </tr>
> >> </table>
>
> >> Javascript:
> >> // find or define current row
> >> var currentRow = "row1">
>
> >> // create new Row and Cells
> >> var cnt = 1;
> >> var newrow = document.createElement("tr");
> >> var cell = document.createElement("td");
> >> var cellText = document.createTextNode("<input type=text
> >> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> >> cell.appendChild(cellText);
> >> newrow.appendChild(cell);
>
> >> // now append the new Row and its Cells to current row
> >> currentRow.appendChild(newrow);
>
> >> Question, that line of
> >> var cellText = document.createTextNode("<input type=text
> >> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
> >> is wrong, that is, it's a text node, not an input node, and I don't
> >> think there's something like createInputNode something, so, how do we
> >> do it?
>
> > You can use something like this as a workaround for old IE and problems
> > with "input type name":
>
> There is no such problem.  You are confusing this with changing the value of
> the `type' property of an `input' element object after the corresponding
> element has been appended.
>
> > elm - node name
> > attributes - object with atttributes
>
> > var createElement = function(elm, attributes){
> >      var div = document.createElement("div"),
>
> Unnecessary; potentially harmful here (a `div' element in a `td' element).
>
> >          element = document.createElement(elm);
>
> OK.
>
> >      for(var p in attributes){
>
> Iterates over enumerable properties of `attributes'.  Better:
>
>   for (var keys = Object.keys(attributes), i = 0, len = keys.length;
>        i < len;
>        ++i)
>
> or pre-ES 5.1 variants thereof.  See also jsx.object.getKeys().
>
> >        element[p]= attributes[p];
>
> Fails to account for the mapping of attribute names that are reserved words
> to special attribute properties (like "for" → "htmlFor"), and of the `style'
> attribute.  See also jsx.dom.setAttr().
>
> >      }
>
> >      div.appendChild(element);
> >      return div.firstChild;
>
> I beg your pardon?  What exactly are you creating the `div' element for if
> you are not returning a reference to it?  Mystical incantation?
>
> > };
>
> > This is just an example and probably code could be more improved.
>
> It is a solution looking for a problem while creating more problems than it
> fails to solve.   The correct way to address the problem actually posed by
> the question (as opposed to your answer) is:
>
>   var input = document.createElement("input");
>   input.name = "partnumber" + cnt;
>   input.id = "partnumber" + cnt;
>   input.className = "autocomplete";
>   cell.appendChild(input);
>
> PointedEars
> --
> Anyone who slaps a 'this page is best viewed with Browser X' label on
> a Web page appears to be yearning for the bad old days, before the Web,
> when you had very little chance of reading a document written on another
> computer, another word processor, or another network. -- Tim Berners-Lee

@PointedEars,
I'm using your syntax,
particularly, the input.className = "autocomplete" part.

So, the code looks like this:
// cell 1
var cell = document.createElement("td");
var cellText = document.createElement('input');
cellText.type = 'text';
cellText.id = 'partnumber'+cnt;
cellText.name = 'partnumber'+cnt;
cellText.className = 'autocomplete';
cell.appendChild(cellText);
newrow.appendChild(cell);

// probably var name of cellProperty is more suited than cellText but
they are the same here

// add some code to make the new row show up right before row id of
"discount" using insertBefore
/* code omitted */


Outcome or rendered HTML:
First, new ROW of input type of text created and in correct position
as expected.

<!-- rendered existing ROW -->
<td>
<input id="partnumber" class="autocomplete ui-autocomplete-input"
type="text" name="partnumber" autocomplete="off" role="textbox" aria-
autocomplete="list" aria-haspopup="true">
</td>
<!-- yes, the predefined element for autocomplete class call is
successful as expected -->


<!-- rendered dynamically created ROW -->
<td>
<input id="partnumber2" class="autocomplete" type="text"
name="partnumber2">
</td>
<!-- no, the autocomplete class call fails -->

Browser: Firefox 16 for windows

What is wrong here?

Thanks.

[toc] | [prev] | [next] | [standalone]


#17436

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-12-03 22:53 +0100
Message-ID<15075341.ROmfG5ADdx@PointedEars.de>
In reply to#17405
justaguy wrote:
^^^^^^^^
Please fix that, this is not a Web forum.  And avoid Google Groups for 
posting, use a newsreader.

> Thomas 'PointedEars' Lahn wrote:
>> […]   The correct way to address the problem actually
>> posed by the question (as opposed to your answer) is:
>>
>> var input = document.createElement("input");
>> input.name = "partnumber" + cnt;
>> input.id = "partnumber" + cnt;
>> input.className = "autocomplete";
>> cell.appendChild(input);

Please trim your quotations to the relevant parts next time.

<http://jibbering.com/faq/notes/>

> @PointedEars,

(AISB.)  The thread and the attribution lines for the quotation levels make 
it clear already whose posting(s) you are referring to.

> I'm using your syntax,
> particularly, the input.className = "autocomplete" part.
> 
> So, the code looks like this:
> // cell 1
> var cell = document.createElement("td");
> var cellText = document.createElement('input');
> cellText.type = 'text';
> cellText.id = 'partnumber'+cnt;
> cellText.name = 'partnumber'+cnt;
> cellText.className = 'autocomplete';
> cell.appendChild(cellText);
> newrow.appendChild(cell);
> 
> […]
> Outcome or rendered HTML:
> First, new ROW of input type of text created and in correct position
> as expected.
> 
> <!-- rendered existing ROW -->
> <td>
> <input id="partnumber" class="autocomplete ui-autocomplete-input"
                                             ^^^^^^^^^^^^^^^^^^^^^
> type="text" name="partnumber" autocomplete="off" role="textbox" aria-
> autocomplete="list" aria-haspopup="true">
> </td>
> <!-- yes, the predefined element for autocomplete class call is
> successful as expected -->
> 
> 
> <!-- rendered dynamically created ROW -->
> <td>
> <input id="partnumber2" class="autocomplete" type="text"
> name="partnumber2">
> </td>
> <!-- no, the autocomplete class call fails -->
> 
> Browser: Firefox 16 for windows
> 
> What is wrong here?

jQuery UI Autocomplete, jQuery UI, and jQuery.  Avoid everything that has 
"jQuery" in it (any capitalization).


PointedEars
-- 
Sometimes, what you learn is wrong. If those wrong ideas are close to the 
root of the knowledge tree you build on a particular subject, pruning the 
  -- Mike Duffy in cljs, <news:Xns9FB6521286DB8invalidcom@94.75.214.39>

[toc] | [prev] | [next] | [standalone]


#17407

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-12-02 08:43 +0100
Message-ID<k9f0rg$ajv$1@speranza.aioe.org>
In reply to#17404
W dniu 2012-12-02 03:46, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
>
>> W dniu 2012-12-02 00:17, justaguy pisze:
>>> I've done such dynamic creation of TR and its TDs a while ago... but
>>> runs into problem.
>>> The thought is, if I have a current TR with ID of "row1", then the
>>> following code should be able to create a new TR and its TDs and
>>> append them to the "row1" Row.
>>>
>>> HTML:
>>> <table>
>>> <tr id="row1">
>>>     <td><input type="text" id="myname" name="myname"><td>
>>>     <td><input type="text" id="mydesc" name="mydesc"><td>
>>> </tr>
>>> </table>
>>>
>>> Javascript:
>>> // find or define current row
>>> var currentRow = "row1">
>>>
>>> // create new Row and Cells
>>> var cnt = 1;
>>> var newrow = document.createElement("tr");
>>> var cell = document.createElement("td");
>>> var cellText = document.createTextNode("<input type=text
>>> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
>>> cell.appendChild(cellText);
>>> newrow.appendChild(cell);
>>>
>>> // now append the new Row and its Cells to current row
>>> currentRow.appendChild(newrow);
>>>
>>> Question, that line of
>>> var cellText = document.createTextNode("<input type=text
>>> name=partnumber"+cnt+ "id=partnumber"+cnt+ "class=autocomplete>");
>>> is wrong, that is, it's a text node, not an input node, and I don't
>>> think there's something like createInputNode something, so, how do we
>>> do it?
>>
>> You can use something like this as a workaround for old IE and problems
>> with "input type name":
>
> There is no such problem.  You are confusing this with changing the value of
> the `type' property of an `input' element object after the corresponding
> element has been appended.

I am refereeing to old IE bug described on 
http://webbugtrack.blogspot.cz/2007/10/bug-235-createelement-is-broken-in-ie.html. 
Of course, problem with setting dynamically attribute "name" is only in 
IE 7 and lower.

>> elm - node name
>> attributes - object with atttributes
>>
>> var createElement = function(elm, attributes){
>>       var div = document.createElement("div"),
>
> Unnecessary; potentially harmful here (a `div' element in a `td' element).
>>           element = document.createElement(elm);
>
> OK.
>
>>       for(var p in attributes){
>
> Iterates over enumerable properties of `attributes'.  Better:
>
>    for (var keys = Object.keys(attributes), i = 0, len = keys.length;
>         i < len;
>         ++i)
>
> or pre-ES 5.1 variants thereof.  See also jsx.object.getKeys().

I tried to use Object.keys many times, but seems that it is very slow. 
See test: http://jsperf.com/loop-for-in-vs-object-keys-foreach/2

And yes, I remember your opinion about those tests :-)

>>         element[p]= attributes[p];
>
> Fails to account for the mapping of attribute names that are reserved words
> to special attribute properties (like "for" → "htmlFor"), and of the `style'
> attribute.  See also jsx.dom.setAttr().

Right. Actually I use mapping for attributes:

         'for' : 'htmlFor',
         accesskey : 'accessKey',
         codebase : 'codeBase',
         frameborder : 'frameBorder',
         framespacing : 'frameSpacing',
         nowrap : 'noWrap',
         maxlength : 'maxLength',
         'class' : 'className',
         readonly : 'readOnly',
         longdesc : 'longDesc',
         tabindex : 'tabIndex',
         rowspan : 'rowSpan',
         colspan : 'colSpan',
         ismap : 'isMap',
         usemap : 'useMap',
         cellpadding : 'cellPadding',
         cellspacing : 'cellSpacing',
         contenteditable : 'contentEditable'

>>       }
>>
>>       div.appendChild(element);
>>       return div.firstChild;
>
> I beg your pardon?  What exactly are you creating the `div' element for if
> you are not returning a reference to it?  Mystical incantation?

I can not be sure now (it was long time ago), but as I remember I did 
this because <input> element had to be append somewhere to create 
properly <input> element with "name" attribute.

However, today is not necessary.

>> };
>>
>> This is just an example and probably code could be more improved.
>
> It is a solution looking for a problem while creating more problems than it
> fails to solve.   The correct way to address the problem actually posed by
> the question (as opposed to your answer) is:
>
>    var input = document.createElement("input");
>    input.name = "partnumber" + cnt;
>    input.id = "partnumber" + cnt;
>    input.className = "autocomplete";
>    cell.appendChild(input);

Well, today I bet that most browsers working with that well. I just 
referred to problems with IE7 and lower during creating dynamically 
<input> element.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#17409

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-12-02 16:11 +0100
Message-ID<5551855.fYihAxhPQP@PointedEars.de>
In reply to#17407
Cezary Tomczyk wrote:

> W dniu 2012-12-02 03:46, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> You can use something like this as a workaround for old IE and problems
>>> with "input type name":
>> There is no such problem.  You are confusing this with changing the value
>> of the `type' property of an `input' element object after the
>> corresponding element has been appended.
> 
> I am refereeing to old IE bug described on
> http://webbugtrack.blogspot.cz/2007/10/bug-235-createelement-is-broken-
> in-ie.html.
> Of course, problem with setting dynamically attribute "name" is only in
> IE 7 and lower.

I have not tested in IE 7.  However, I have created a testcase and tested in 
IE 6.0.2800.1106 on Wine XP SP1 (IEs4Linux):

<http://PointedEars.de/scripts/test/dom/input-submit>

The results of my tests are:

- Without further measures the appended control is not accessible by name
  via the `elements' collection.  (Insofar the entry is correct.)

- Without further measures the appended control *is* submitted.  (The entry
  is incorrect from there.)

In conclusion, it is probably _not_ the implementation of createElement() in 
MSHTML that is broken there, but that of appendChild() and similar methods.  
It is therefore incorrect that to work around this it would be absolutely 
necessary to resort to what is suggested there.  [And JFYI, what you have 
posted here has *nothing* to do with what is suggested there.]

As we have found out here (or was it in de.comp.lang.javascript?) years ago, 
a workaround is to add the control to the `elements' collection if it is not 
yet part of it:

  var input = document.createElement("input");
  var name = "foo";
  input.name = name;
  input.value = "bar";
  form.appendChild(input);

  /* workaround for IE < 8 */
  if (typeof form.elements[name] == "undefined")
  {
    form.elements[name] = input;
  }

As you can see, a disadvantage of that approach is that you lose the 
collection functionality if there is already a control with the same name.  
If that is a problem, I think you will have to combine it with other 
approaches or refer to the new control by other means than the `elements' 
collection.  (But someone – Richard Cornford? – might have already provided 
a solution to that problem as well.)

The same problem and workaround exists with other collections.  IIRC they 
exist with iframes and window.frames[…] as well.
 
>>>       for(var p in attributes){
>>
>> Iterates over enumerable properties of `attributes'.  Better:
>>
>>    for (var keys = Object.keys(attributes), i = 0, len = keys.length;
>>         i < len;
>>         ++i)
>>
>> or pre-ES 5.1 variants thereof.  See also jsx.object.getKeys().
> 
> I tried to use Object.keys many times, but seems that it is very slow.

At least it is reliable and can be rather easily emulated (for enumerable 
properties) down to ES 3.

> See test: http://jsperf.com/loop-for-in-vs-object-keys-foreach/2
> 
> And yes, I remember your opinion about those tests :-)

Good.  You should also know that you are comparing apples and oranges here. 

A for-in statement is _not_ equivalent to either foreach (or the E4X `for 
each') or Object.keys().  By contrast, it iterates over own and *inherited* 
*enumerable* properties in *implementation-dependent* (in ES3, arbitrary) 
order; the iterator is the property name, not the property value.

Object.keys() returns a reference to an Array of the names of all *own* 
enumerable properties (in the same implementation-dependent order as for 
for-in), and *only* those.  [Which is why if you want to emulate 
Object.keys() for enumerable properties, you have to use 
Object.prototype.hasOwnProperty() or emulations thereof.]

>>>         element[p]= attributes[p];
>>
>> Fails to account for the mapping of attribute names that are reserved
>> words to special attribute properties (like "for" → "htmlFor"), and of
>> the `style' attribute.  See also jsx.dom.setAttr().
> 
> Right. Actually I use mapping for attributes:
> 
>          'for' : 'htmlFor',
>          accesskey : 'accessKey',
>          codebase : 'codeBase',
>          frameborder : 'frameBorder',
>          framespacing : 'frameSpacing',
>          nowrap : 'noWrap',
>          maxlength : 'maxLength',
>          'class' : 'className',
>          readonly : 'readOnly',
>          longdesc : 'longDesc',
>          tabindex : 'tabIndex',
>          rowspan : 'rowSpan',
>          colspan : 'colSpan',
>          ismap : 'isMap',
>          usemap : 'useMap',
>          cellpadding : 'cellPadding',
>          cellspacing : 'cellSpacing',
>          contenteditable : 'contentEditable'

Looks good to me.  I will augment the mapping in dom.js with some of those.

>>>       }
>>>
>>>       div.appendChild(element);
>>>       return div.firstChild;
>>
>> I beg your pardon?  What exactly are you creating the `div' element for
>> if you are not returning a reference to it?  Mystical incantation?
> 
> I can not be sure now (it was long time ago), but as I remember I did
> this because <input> element had to be append somewhere to create
> properly <input> element with "name" attribute.

You misremember.

> However, today is not necessary.

It never was.

>>> };
>>>
>>> This is just an example and probably code could be more improved.
>>
>> It is a solution looking for a problem while creating more problems than
>> it fails to solve.   The correct way to address the problem actually
>> posed by the question (as opposed to your answer) is:
>>
>>    var input = document.createElement("input");
>>    input.name = "partnumber" + cnt;
>>    input.id = "partnumber" + cnt;
>>    input.className = "autocomplete";
>>    cell.appendChild(input);
> 
> Well, today I bet that most browsers working with that well. I just
> referred to problems with IE7 and lower during creating dynamically
> <input> element.

See above and below.

Please trim your quotes.


PointedEars, with a random but fitting signature
-- 
> If you get a bunch of authors […] that state the same "best practices"
> in any programming language, then you can bet who is wrong or right...
Not with javascript. Nonsense propagates like wildfire in this field.
  -- Richard Cornford, comp.lang.javascript, 2011-11-14

[toc] | [prev] | [next] | [standalone]


#17412

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2012-12-02 18:48 +0100
Message-ID<k9g4a1$54q$1@speranza.aioe.org>
In reply to#17409
W dniu 2012-12-02 16:11, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
[...]
>> I am refereeing to old IE bug described on
>> http://webbugtrack.blogspot.cz/2007/10/bug-235-createelement-is-broken-
>> in-ie.html.
>> Of course, problem with setting dynamically attribute "name" is only in
>> IE 7 and lower.
>
> I have not tested in IE 7.  However, I have created a testcase and tested in
> IE 6.0.2800.1106 on Wine XP SP1 (IEs4Linux):
>
> <http://PointedEars.de/scripts/test/dom/input-submit>

Nice test.

[...]
> As we have found out here (or was it in de.comp.lang.javascript?) years ago,
> a workaround is to add the control to the `elements' collection if it is not
> yet part of it:
>
>    var input = document.createElement("input");
>    var name = "foo";
>    input.name = name;
>    input.value = "bar";
>    form.appendChild(input);
>
>    /* workaround for IE < 8 */
>    if (typeof form.elements[name] == "undefined")
>    {
>      form.elements[name] = input;
>    }
>
> As you can see, a disadvantage of that approach is that you lose the
> collection functionality if there is already a control with the same name.
> If that is a problem, I think you will have to combine it with other
> approaches or refer to the new control by other means than the `elements'
> collection.  (But someone – Richard Cornford? – might have already provided
> a solution to that problem as well.)

Personally I do not care about IE7 and lower. Currently I am focusing on 
IE8 and higher. However, thanks for explanation.

[...]

>> I tried to use Object.keys many times, but seems that it is very slow.
>
> At least it is reliable and can be rather easily emulated (for enumerable
> properties) down to ES 3.

Yes, that's true.

>> See test: http://jsperf.com/loop-for-in-vs-object-keys-foreach/2
>>
>> And yes, I remember your opinion about those tests :-)
>
> Good.  You should also know that you are comparing apples and oranges here.

Maybe. It is just a overall test.

> A for-in statement is _not_ equivalent to either foreach (or the E4X `for
> each') or Object.keys().  By contrast, it iterates over own and *inherited*
> *enumerable* properties in *implementation-dependent* (in ES3, arbitrary)
> order; the iterator is the property name, not the property value.
>
> Object.keys() returns a reference to an Array of the names of all *own*
> enumerable properties (in the same implementation-dependent order as for
> for-in), and *only* those.  [Which is why if you want to emulate
> Object.keys() for enumerable properties, you have to use
> Object.prototype.hasOwnProperty() or emulations thereof.]

I agree with you. Just forgot to get only direct properties of object. I 
use:

"   [...]
for (key in params) {
     if (Object.prototype.hasOwnProperty.call(params, key)) {
     [...]
"

[...]
>> I can not be sure now (it was long time ago), but as I remember I did
>> this because <input> element had to be append somewhere to create
>> properly <input> element with "name" attribute.
>
> You misremember.

Yes, it's possible.

>> However, today is not necessary.
>
> It never was.

I have no reason to not believe you.

[...]
> Please trim your quotes.

Should be better now.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#17416

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-12-02 19:35 +0100
Message-ID<2075691.byxZkP05Om@PointedEars.de>
In reply to#17412
Cezary Tomczyk wrote:

> W dniu 2012-12-02 16:11, Thomas 'PointedEars' Lahn pisze:
>>> Cezary Tomczyk wrote:
> [...]
> Personally I do not care about IE7 and lower. Currently I am focusing on
> IE8 and higher.

Given the market share of the versions you do not care about, you should 
reconsider, as bad as that sounds to both of us.

> However, thanks for explanation.

You're welcome.
 
>>> See test: http://jsperf.com/loop-for-in-vs-object-keys-foreach/2
>>>
>>> And yes, I remember your opinion about those tests :-)
>>
>> Good.  You should also know that you are comparing apples and oranges
>> here.
> 
> Maybe. It is just a overall test.

Which is pointless if you do not consider that not only the functionality of 
the tested features is fundamentally different but also that you are working 
against the advantages of certain variants.  Why forEach()?  Why i++ where 
you count with j?  What about ordering?

>> A for-in statement is _not_ equivalent to either foreach (or the E4X `for
>> each') or Object.keys().  By contrast, it iterates over own and
>> *inherited* *enumerable* properties in *implementation-dependent* (in
>> ES3, arbitrary) order; the iterator is the property name, not the
>> property value.
>>
>> Object.keys() returns a reference to an Array of the names of all *own*
>> enumerable properties (in the same implementation-dependent order as for
>> for-in), and *only* those.  [Which is why if you want to emulate
>> Object.keys() for enumerable properties, you have to use
>> Object.prototype.hasOwnProperty() or emulations thereof.]
> 
> I agree with you. Just forgot to get only direct properties of object. I
> use:
> 
> "   [...]
> for (key in params) {
>      if (Object.prototype.hasOwnProperty.call(params, key)) {
>      [...]
> "

Unless you cannot be certain that the value of `params' refers to an object 
that has Object.prototype in its prototype chain, this is needlessly 
inefficient.  Keep in mind that identifier lookup is a runtime feature.  In 
each iteration `Object' will have to be resolved against the scope chain 
(usually up to the global object), then its `prototype' property will have 
to be resolved against the prototype chain, and so forth.

Consider this instead:

  for (var key in params)
  {
    if (params.hasOwnProperty(key))
    {
      // …
    }
  }

The least you should do is to cache the value of 
`Object.prototype.hasOwnProperty', maybe even in a bound variable of a 
closure (as can be seen in JSX), if you do not call it through the prototype 
chain.

  /*
   * Or `Object.prototype', but `{}' appears to have a shorter
   * scope chain, which might win over the longer prototype chain
   */
  var _hasOwnProperty = {}.hasOwnProperty;

  for (var key in params)
  {
    if (_hasOwnProperty.call(params, key))
    {
      // …
    }
  }

It might be useful to combine these:

  var hasHasOwnProperty =
    (typeof params.hasOwnProperty == "function")
      ? params.hasOwnProperty
      : {}.hasOwnProperty;

  for (var key in params)
  {
    if (_hasOwnProperty.call(params, key))
    {
      // …
    }
  }

That would allow the object to inherit or define its special 
hasOwnProperty() method, and use the built-in as fallback.

> [...]
>> Please trim your quotes.
> 
> Should be better now.

Yes, thanks.
 

PointedEars
-- 
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
  -- Richard Cornford, cljs, <f806at$ail$1$8300dec7@news.demon.co.uk>

[toc] | [prev] | [next] | [standalone]


#17417

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2012-12-02 19:39 +0100
Message-ID<1562636.Ll19dNWgsJ@PointedEars.de>
In reply to#17416
Thomas 'PointedEars' Lahn wrote:

> Consider this instead:
> 
>   for (var key in params)
>   {
>     if (params.hasOwnProperty(key))
>     {
>       // …
>     }
>   }
> 
> The least you should do is to cache the value of
> `Object.prototype.hasOwnProperty', maybe even in a bound variable of a
> closure (as can be seen in JSX), if you do not call it through the
> prototype chain.
> 
>   /*
>    * Or `Object.prototype', but `{}' appears to have a shorter
>    * scope chain, which might win over the longer prototype chain
>    */
>   var _hasOwnProperty = {}.hasOwnProperty;
> 
>   for (var key in params)
>   {
>     if (_hasOwnProperty.call(params, key))
>     {
>       // …
>     }
>   }
> 
> It might be useful to combine these:
> 
>   var hasHasOwnProperty =
        ^^^^^^^^^^^^^^^^^
That must _hasOwnProperty.  I wrote the hasHasOwnProperty() approach later 
but it did not work well with boolean expressions, so I reverted it (only 
partially, apparently).

>     (typeof params.hasOwnProperty == "function")
>       ? params.hasOwnProperty
>       : {}.hasOwnProperty;
> 
>   for (var key in params)
>   {
>     if (_hasOwnProperty.call(params, key))
>     {
>       // …
>     }
>   }


PointedEars
-- 
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
  -- Richard Cornford, cljs, <f806at$ail$1$8300dec7@news.demon.co.uk>

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web