calculating in table made by createElement and appendChild

L

Lasse Reichstein Nielsen

following on from the subject of assigning events to dynamically
created elements, i would like to ask some advice on how to assertain
when there is only one row in the table.

If you have a reference to the table, it is easy:
tableRef.rows.length == 1
if(n = 1){

You mean
if(n == 1){

/L
 
K

kie

so something similar to this::?

function removeRow(){ //if row is last row, it cannot be deleted

for( var node = this.parentNode; node; node=node.parentNode)
if(node.parent.rows.length != 1){
alert('Cannot remove last remaining row');
break;
}else{
if(node.tagName=="TR"){
node.parentNode.removeChild(node);
break;
}
}
}

the object 'this' comes from the onClick event of the button in the
row of the dynamic table created by the 'createElement' function. see
(http://www.kieran.f2s.com/removeChild/working.htm)

is this "removeRow" function on the right track, and if so, can it be
modifed to remove all of the rows withing the table?
 
D

Dom Leonard

kie said:
so something similar to this::?

function removeRow(){ //if row is last row, it cannot be deleted

for( var node = this.parentNode; node; node=node.parentNode)
if(node.parent.rows.length != 1){
alert('Cannot remove last remaining row');
break;
}else{
if(node.tagName=="TR"){
node.parentNode.removeChild(node);
break;
}
}
}

the object 'this' comes from the onClick event of the button in the
row of the dynamic table created by the 'createElement' function. see
(http://www.kieran.f2s.com/removeChild/working.htm)

is this "removeRow" function on the right track, and if so, can it be
modifed to remove all of the rows withing the table?

Personally I would prefer to step back and modify the approach a little.
Basically the page starts with one table row defined in HTML, more rows
can be added and deleted, each row has a unique sequence number, and at
some point you wish to have an index of the rows. Rather than create
this index from the DOM, I would use a "factory" object to create and
delete rows and take care of indexing as well. A simple "tableRow"
object might go:

var tableRow = { // factory object

// initialise to account for first row generated in HTML
// with lineId of 1

lineId: 2, // next line sequence number for new rows
lineExists: [false,true], // lookup table by lineId
lineIndex: [1], // array of lineId's on page

create: function ()
{
var oRow = document.createElement('TR');
var lineId = this.lineId++;
var rowId = "row+" + lineId;
var delFunction =
this.makeDelFunction(this, lineId, rowId);

oRow.id = rowId;
this.lineExists[ lineId] = true;
this.reIndex();
return {oRow: oRow,
lineId: lineId,
delFunction: delFunction};
},
makeDelFunction: function( tableRow, lineId, rowId)
{
return function() {tableRow.remove( lineId, rowId)};
},
remove: function( lineId, rowId)
{ var oRow;
if(this.lineIndex.length <= 1)
{ alert("Cannot remove last remaining row");
return;
}
oRow = document.getElementById( rowId);
oRow.parentNode.removeChild(oRow);
delete this.lineExists[ lineId];
this.reIndex();
calculateTab(2,0); // whatever needs doing
},
reIndex: function()
{
this.lineIndex.length=0; // start again;
for(var i = 0; i < this.lineExists.length; ++i)
{
if(this.lineExists)
this.lineIndex.push(i);
}
},
getIndex: function()
{ return this.lineIndex;
}
}

Then in detail_row(), call tableRow.create and, from the returned
object, extract the TR element, the line number and the remove function
for setting on the ButtonSupprimer element - removeRow() above is no
longer used, and neither is globalClaimLnsRowNum made use of.

Later instead of recreating the index, try
a_ids = tableRow.getIndex();
j = a_ids.length;
and in the HTML row definition, include
onclick="tableRow.remove(1, 'row_1')"
as the click handler for the remove button.

As noted in another thread, there are complexities and probable bugs
remaining the code. One I noticed and commented out was in detail_row:
tablebody2.appendChild(oRow);
// formation.appendChild(tablebody2);
since tablebody2 is already a child node of formation!!!

You may wish to check the NG FAQ as well:
http://jibbering.com/FAQ/
It has some very useful trim and decimal formatting routines (amongst
other goodies)


HTH and Good luck!

Dom
 
K

kie

wow Dom, this is new ground for me, i've never used a factory
object/mthod before. i can find information on them in c++ groups, but
not much relating to javascript. so i can grasp the principle of it:

from comp.lang.c++ : "It's a standard OOP term for an object that
contains an interface for creating other objects--so like a factory it
builds things. Factory methods in the object allow derived classes to
specify what type of object is actually created using the virtual
mechanism."

if i call the object factory "tableRow.create;" after i have
discovered the 'tbody' element where the dynamic rows will go, i.e.:

var tablebody2=formation.getElementsByTagName('tbody')[0];
tableRow.create;
//rowSec2=document.createElement('TR');
then i encounter problems with the "appendChild" method. or should i
not comment out the object assigning of "rowSec2", because the
"tableRow" object factory is only concerned with the indexing and
removal of rows, and not assigning elements to the "TR" row object?

i know nothing about this, i should read up on the subject, do you own
or recommend any of the following:?

Principles of Object-Oriented Programming in Java 1.1: The Practical
Guide to Effective, Efficient Program Design by James W. Cooper,
Ventana Communications

Design patterns : elements of reusable object-oriented software
by Erich Gamma, et al

Concurrent Programming in Java: Design Principles and Patterns (The
Java Series)
by Doug Lea;

also if there are any links reading to examples of factory
objects/methods, i'd like to check them out.

thanks for all your help, kie

attempt link: http://www.kieran.f2s.com/remove_rows_factory_object.htm
 
D

Dom Leonard

kie said:
this is new ground for me, i've never used a factory
object/mthod before.

<grin> I think you might have. </grin> I picked up the term from the
W3C DOM2 recommendation, core section "1.1.2 Memory Management",
referring to factory methods as creating instances of objects [without
the new operator provided in call]. In this sense document.createElement
is one example of a well known factory method.

i can find information on them in c++ groups, but
not much relating to javascript. so i can grasp the principle of it:

from comp.lang.c++ : "It's a standard OOP term for an object that
contains an interface for creating other objects--so like a factory it
builds things. Factory methods in the object allow derived classes to
specify what type of object is actually created using the virtual
mechanism."

Glad to see the W3C guys knew what they were talking about :)

My reasons for noting the "tableRow" object as a factory object were
two-fold: for maintenance purposes it provides a clue that object
methods would create objects without themselves being called with the
"new" operator, and by placing table row creating, removing and indexing
in one spot, implementation code can be modififed or optimised with
minimal impact on outside code and testing. [FWIW the posted code is not
optimal, and has the typo "row+" instead of "row_" which to some extent
"worked" because it was not optimal. The beauty is that this can be
fixed with minimal or no changes to calling code.].

if i call the object factory "tableRow.create;" after i have
discovered the 'tbody' element where the dynamic rows will go, i.e.:

var tablebody2=formation.getElementsByTagName('tbody')[0];
tableRow.create;
//rowSec2=document.createElement('TR');
then i encounter problems with the "appendChild" method.

Sorry for any confusion, it was not intentional. detail_row code would
be ammended along the lines of:

var oResult = tableRow.create();
// returns an object with
// oResult.oRow = the TR element created
// oResult.lineId = a line sequence number
// oResult.delFunction = a function object
...
rowSec2 = oResult.oRow; // the TR element
...
sel2.id='two_d_cmb_goods__' + oResult.lineId;
// use the line sequence number provided wherever
// globalClaimLnsRowNum was used.
...
// and use the remove function returned by .create()
ButtonSupprimer.onclick = oResult.delFunction;

<snip>
Sorry can't comment on any of the books. I tend to use resources
available on the Internet - ebooks for preference, but articles when
needed. A good thing the Internet still functions for research (so far).


I would encourage you to continue asking questions of the group by
composing cut down pages and code samples related to individual
programming techniques - there is work involved in preparing the
question but it maximises the chances of assistance. I suspect further
line by line discussion of this page will be of diminishing interest, so
if you like (and this is not a general invitation) feel free to email me
with a working email address for return attachments. If nothing else, we
might be able to sort out a good text editor for you to use :)

kind regards,
Dom
 
K

kie

if you like (and this is not a general invitation) feel free to email me
with a working email address for return attachments. If nothing else, we
might be able to sort out a good text editor for you to use :)

thanks, dom. i've just done it.

the object factory works well, and i understand how the code works, i
am having trouble finding other examples of js object factorys
however.

using the factory in conjunction with one table i changed the 'remove'
section to:

remove: function( lineId, rowId)
{ var oRow;
alert(this.lineIndex.length);
if(this.lineIndex.length <= 2)
{ alert("Cannot remove last remaining row");
return;
}

to make it work. i'm wondering, why when there is only one row in the
dynamic table remaining, does the 'this.lineIndex.length' emerge as
the value 2? is it taking into account the none dynamic '<tr>'
elements?

so i added a second table, and then a third, each with one row.
on two tables the 'lineIndex.length' was 3, on three is was 4.

this causes a problem when detecting the presence of a last row in a
table. the conclusion i jump to is to make a loop using the table id
or parentNode, like:

remove: function( lineId, rowId)
{ var oRow;
//alert(this.lineIndex.length);
var i;
var n_count_rows = 0;
for( var node = this.parentNode; node; node=node.parentNode){
if(node.tagName=="TR"){
for (i=0; i<this.lineIndex.length; i++){
n_count_rows = n_count_rows + 1
alert(n_count_rows);
}
}
}
if(n_count_rows < 2)
{ alert("Cannot remove last remaining row");
return;
}
//if(this.lineIndex.length <= 2)
//{ alert("Cannot remove last remaining row");
// return;
//}
oRow = document.getElementById(rowId);
oRow.parentNode.removeChild(oRow);
delete this.lineExists[lineId];
this.reIndex();
calculateTab(2,0); // whatever needs doing

do you know a more concise way of doing this, such as replacing:

if(this.lineIndex.length <= 2)
{ alert("Cannot remove last remaining row");
return;
}

for

if(this.lineIndex.parentTableId.count = 1)
{ alert("Cannot remove last remaining row");
return;
}

the lengthy version of this code can be found at:
http://www.kieran.f2s.com/table(3).html
upon viewing the source of the html page, the object factory is at the
very top, followed by the dynamic table creation code.

thanks for any help, kie
 

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,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top