Ooops! "I am not creating a form element..." on the previous post, should be = "I am NOW creating a form element...).
Main Topics
Browse All TopicsI am new to dynamic table creation. This table is simple in concept.
Can add as many tables as nec. Each table can add/delete/toggle rows.
Table row 1): Cell1:Title, Cell2:Min/Max, Cell3:closeTable
Table row 2): Cell1:Content(form), Cell2:min/max, Cell3:move row up or down, Cell4:delete this row
Table row 3): Cell1: "Add Additional row to table" link.
Of course, this object and uses "this" keyword. No "getElementById()" used in this one. I am close but am running into some walls. Major wall: Is my table structure right where I am adding the (dContent). Should I be iterating many different (dContent) objects per row and then append the content to them? Should I remove the (dConetnt) object altogeather and track each row inIndex?
The "onchange" select functions are a separate piece. I am planning appending the forms dynamically as well but, I have that piece under control. So for now just ignore the form behavior inside the rows.
Any help is appreciated.
...Day 2 afer posting. Still nothing. I mean, I am making progress but, it sure would be nice if someone could help speed up the process. Up to this point was fairly easy. If I could use an ID reference it would be even eaiser. But I can't. The tracking of the rowIndex should'nt be nec since I am putting it in a parent object. I should just be able to move/ remove/ hide, the object. I tried some variations of (this.dConent.childNode(ge
Bout to trash it and rewrite with a non Obj (id="id' +i'")..guess I can track the rows (inRowIndex) that way too. It seems awfully long and nasty though, when I am so close.
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
Just noticed this. Sorry for the delay.
Even though you don't see it (most) html, you really need to create a TBODY element in your table.
The original question does not create or use a tbody element.
In order to see what is happening, it would help to have access to drillDowns.js and any other javascript files referenced by that file.
Thanks "HonorGod" for getting back to me. Notice too, that my i(addCurrentRow(this)) now adds the row in the correct place but it does it in a weird way and doesnt track the rowNum correctly, It does reorder correctly though if they are deleted. I realize that this would be a great candidate for a private(Func) since It would benefit me to get that (tbl = this.dTable.rows) reference.
K, ive confused you enough now. I'll let you do your expert thang. Thanks again!
Um...sure. If I can add the current in place then I dont need to move the row up or down. So it would save time. However, once I do that, I have a little trickier problem, which is that I will need to put that form into a hideable object in that row. So, imagine if you will that each row will have:
table Header:
NewRow:
cell1: form content (hideable)
cell2:addRowIn current position
cell3: and deleteRow.
footer
Conceptually easy, but then again so is going from the earth to the moon. Damn Rocketship makes it hard though.
So you pick. And sorry for the uncleanlyness of my code. Looks like 10 script kitties came over and spent the night on my computer. :)
Part of the problem with addCurrentRow() is that you have it coded to apparent expect a row number or something:
function addCurrentRow( num ) {
if ( num == null ) {
num = nextRow;
} else {
iteration = num + ROW_BASE;
}
but what you are passing is a button object:
raEl.onclick = function () {addCurrentRow( this )};
So, when the Add button is clicked, the object reference to this button is being passed to the addCurrentRow function.
No, no not a nested table I mean in each row, the first cell, would be (collapse/exapnd), so like maybe a dive or seomthing in the first cell that can be collapsed by a cell in the same row:
[table header]
<tr><td><div><form></div><
[table footer: "Add New Row"]
Sorry for the confusion.
I cleaned up the mess a little bit too. I had left some things in there from the original version. Here is a new one if it helps. I know this thread is getting long. And thank you for pointing out that target problem on the button, Easy to get confused when using "this" so many times.
The check boxes, radio, etc that are there now will be replaced with buttons:
<tr><td>[collapsible form or div or whatever]</td><td>[+/-]</t
The beginning of addCurrentRow() still doesn't make sense, given that the calls to this routine are all of the form:
addCurrentRow( this )
if ( num == null ) {
num = nextRow; // This is an integer value
} else {
iteration = num + ROW_BASE; // This is adding an integer to an object reference
}
Here are the steps I performed:
- Select the "New Window" text in the input box
- Type "A" (i.e., capital A)
- Click "Create New Window" button
- Click on the "Add Another Ctieria Set" text (should that be "Criteria"?)
And it looks like:
Ok , I see:
Add Another criteria = add a row to the end of the table (before the "add another criteria set text)
Add Row = addRow in this row index. (add it right here in this position, not at the end of the row (-1))
delete = delete this row.
and of course we will be adding new one, which will show or hide the first cell of the table.
The row inputs that are there now, and the checkbox will not be there. In the place where the <input> is we will have the form from the original script. So imagain that the input that is there now will be a div (in the row) that will be expandable/collapsible.
I see I drew the form area as another row...it could all be in one row, or as an additional row that gets collapsed by the first one. ..doesnt matter really, for functionality sake that is. The space under the buttons is nothing, if that form is another row then its an empty cell I guess but I would prolly make the row colSpan all the way across, if we go with the "Additional collapsible row" vs. "DIV/form in the same row".
Ok, here is exactly what I am saying.
Now, could the form exist in the dotted area? Then we collapse the DIV in each row instead of the row itself. Thats what I been trying to say. We create a div (per row) and append a child element -(form)- into it.
So, in essence, we create a single cell in the new row and, in that we put the <form> and table controls (+/ah/d):
<tr><td vAlign="top" hAliign="right">
<button><button><button>
<div style="float:left" id="this.childNode - or ("childDiv" +rowNum)>
<form>AppendedChild of parent div</form>
</div>
</td>
</tr>
Like that?
hmmm, I guess we could do that. Seems like a lot of overhead though. And if I add functionality to search through the tables at some point, get to the form elements, etc. the hash will be awfully big. Do you agree? I think one cell, with all the trimmins would be a little lighter. But, hey, you are the Expert. I can always change the table structure later.
Those damn rowIndexes and current rows...thats where this gets confusing for me. I feel like I am right there though. Little light bulbs goin off everywhere now. "This" keyword...very nasty and powerful. :)
I could go ahead and slap some (setAttribute("id", "commonNames") on those divs if you want. Anything to get us closer to the meat and potatoes. Though I see the importance of structure now. These tables really get the visual cortex creating table structures in the mind. Gotta keep that 3D model fresh and clear you know?
My reasoning behind using a nested table was to get as close to the image you had above as possible. Unfortunately, I have lots to learn about CSS, so there may be some nice (and hopefully easy) way of using CSS instead of tables. However I haven't been able to find anything in the CSS books that I have that answers this question for me. :-(
Plus, I think having the security of "your very own expert", helps to relax the process a little and think outside the box. This is the first time I have collaborated with someone like that online. Very cool. Seems like anything can be accomplished with 2 great minds. You are the Sempi and I am the student. hahah sorry. :)
On the unique attribute post: It will only be unique to a parent that contains it. It won't be unique to the document itself. I think using the parentNode.childNode(getEl
Here is the correct cell layout now. I created some CSS and found some pieces that were not right. I was calling "raEl" (AKA Delete button) twice and appending after into the last form as well. Also had mistyped my CSS. Corrected that And created some new ones for all the row/div components.
I added another form for the rowName and set that content form with a border. They all layin out now...chillin in the sun. Where I want to be. :)
Make it Unique to the page how? Name +Iterator? I mean the user can create as many tables of these as they want. If they create another table and our controls are set to a (document.getElementById()
Ok, so "Delete" not workin because we change the nesting inside the row now. It as referencing the parent table as:
function deleteCurrentRow(obj)
{
var delRow = obj.parentNode.parentNode;
var tbl = delRow.parentNode.parentNo
var rIndex = delRow.sectionRowIndex;
var rowArray = new Array(delRow);
deleteRows(rowArray);
reorderRows(tbl, rIndex);
}
How we gonna fix that? look for getElembyTag != "TR"?
Ok, I created an ID for each div and the table. I set an alert in the Delete function to tell us what "obj.parentNode.parentNode
So, our structure is:
<tr>
<td>
<mainDiv>
<rowNameDiv></div>
<ctrlsDiv></div>
<contentDiv></div>
</div>
</td>
</tr>
and I think Delete is tryin to find (the Table)
Ok, HG, I found it. Delete went home and couldnt find his Papa this time. So I found papa for him. Delete working fine now. Here is the working target.
function deleteCurrentRow(obj)
{
var delRow = obj.parentNode.parentNode.
//alert(delRow.ID);
var tbl = delRow.parentNode.parentNo
var rIndex = delRow.sectionRowIndex;
var rowArray = new Array(delRow);
deleteRows(rowArray);
reorderRows(tbl, rIndex);
}
New code with working delete function:
This is in my (hideRow()) function as the pointer to the contentDiv:
hideRowID = obj.parentNode.parentNode.
Lemme guess, won't work in FF? and is prolly finding the (table.tr.td.mainDiv.item(
ok. Interesting changes.
I started by looking at your deleteCurrentRow(), and would like to suggest that you make your code more general (i.e., less specific). For example, when I see code like:
var delRow = obj.parentNode.parentNode.
This is very specific to the environment. This only works when the object passed to this routine (i.e., "obj", or deleteCurrentRow( this ) ) actually refers to a button within a cell within a row.
If we use something like this, it is generally reusable:
This allows the assignment to be:
var delRow = thisRow( obj );
It also allows some code to be include to check for an unexpected situation (e.g., if the
document element passed to this routine (obj) is not contained within a TR) by:
if ( delRow ) {
// Process the containing TR element
} else {
alert( 'Error: specified element is not within a table row' );
}
yup...
Now, the next question is, given a row as shown above:
http://www.experts-exchang
What do you want to have it look like after the "ah" button is clicked?
no, that's fine. I just want to understand the difference between clicking on the AH, vs what we see when you click on the "Add Another Criteria" row.
It sounds like the difference is the placement of where the row will be added. When you have no data row, you must click on the "Add Another Criteria" footer to add the first row.
When you click on an AH button should the row be added after the current row, or before?
I presume that you want it after.
Um....before would be fine. Actually, I am going to call the (AddRow) function just after the firstTable is created. That way the user will have a TR already in view. The "AH" will allow the user to put a row in place.... the relationship between the rows will be <tr>"AND"<tr>"AND"<tr>... to the DB that is. So it is important for the user to be able to either 1.) Create a row in place OR 2.) Move the rows up or down. I think creating in place is a little easier and user friendly. Both could be nice as well but I don't wanna get greedy with your help. Thanks again. :)
Imagine that the peoeple using this will be creating like 5 rows at a time...then configuring the row data. The ability to move the rows might be a little better than having to delete a configured row and recreate it in the right spot. I guess my current design doesnt have much flex room if they create a row out of place. Hmmm. Well, lets just keep going. I bet I can manage moving the rows... and reordering them in specific heirarchy after a move is not paramount either... I don't think. We should never be able to sort these rows really so I think we are safe.
Notes:
- AddRow() is only called by onAddRow, which is not passing any value.
- In order to use insertRow(), we must be able to specify the position at which the new row
is to be added.
- So, in order to add a new row after the current row, we really need to be able to
determine the current row number. One way to do this is:
- Locate the containing table,
- iterate over the rows in the table, looking for the current row in question
- For example, we might be able to use something like:
- alright, so let's change the "thisRow()" to be "thisNode()" so we can find various containing element.
- we can then create a rowNum() routine to use this to determine the row # of the row containing the ah button we pressed:
- I also changed the references to "num" within the addCurrentRow() routine to be to "obj", so that the object passed is more accurately reference.
Please note that row numbers start at 0, so the rowNum() returned will be from 0..N (where N is the number of rows in the table).
Given this, we can then make use of the fact that we have a valid row number.
In order to insert a row before the current row number, however, we need to
decrement the value returned.
However, we need to be careful to check for an "error" condition. If the object
passed to the rowNum() routine is not within a table, the row number that gets
returned will be -1. This was chosen to match the value specified to insertRow().
If it is passed a -1, then a new row is created at the end of the table.
Does this help, and make sense?
Man, that's some fancy codin there HG. I like it:
function rowNum( obj ) {
var row = thisNode( obj, 'TR' ); // Locate containing row
var result = -1;
if ( row ) {
var tbl = thisNode( row, 'TABLE' ); // Locate containing table
if ( tbl ) {
for ( var num = 0; num < tbl.rows.length; num++ ) {
if ( tbl.rows[ num ] == row ) {
return num;
}
}
}
}
return result;
}
function addCurrentRow( obj )
{
if (obj == null) {
obj = nextRow;
} else {
//alert( 'rowNum: ' + rowNum( obj ) );
iteration = obj + ROW_BASE;
}
alright. I see some problems... :-(
in addCurrentRow(), you have some confusing code.
Rewrite the beginning, I now have it looking like:
This is where things start to get a bit messy.
You begin by creating a new div, which is fine.
// Create a main parent div ito go in a single row cell
var mainDiv = document.createElement( 'div' );
mainDiv.setAttribute( 'height', 160 );
mainDiv.setAttribute( 'ID', 'mainDiv' );
mainDiv.className = 'mainDiv';
Then, you create the first (zeroth) cell for the new row:
// Create a single cell to go in the row that will hold all the divs
var cell0 = row.insertCell( 0 );
cell0.setAttribute( "vAlign", "top" );
which is like the following HTML:
<tr>
<td valign='top'></td>
</tr>
Then, you put the reference to the new cell into the div.
cell0.appendChild( mainDiv );
This is not good. How is this sequence supposed to be represented?
Is the newly created cell to be removed from the row to which it was
just added? Or, are we really supposed to have two references to the
same cell element?
I'm still reading the code in an attempt to understand what, exactly,
you are trying to do.
What would the HTML look like?
<tr>
<td valign='top'>
<div id='mainDiv' class='mainDiv'>
<div id='RowName' class='divRowName'>
</div>
<div id='DivCtrls' class='divCtrls'>
<input type='button' ...>
<input type='button' ...>
<input type='button' ...>
</div>
<div id='DivContent' class='divContentOn'>
<form id='Form2' methoc='POST' action='#'>
<input type='text' name=?? size='40' value='Content #'>
</form>
</div>
</div>
</td>
</tr>
So, here is the code again, I removed some things... this a little better? Also, I see what the function was doing for add row here. You were trying to determine if it was the first row, then don't put at position -1. But this is ok because, technically I am going have the tabel appear with a row in it. Therefore it will correctly with a starting row. So, we good there.
I think we are good on the:
addRowHere. = good
Delete is good =good
toggle = not good yet.
here is the modified code. This seems a little better:
As far as the toggle is concerned, I can't tell you what to do with that until you answer the question posed above:
http://www.experts-exchang
Ok, I don't want to hide the ROW on toggle. I want to hide the content div. That would still leave the row showing the buttons and the rowName. I thought we could grab the button.parentNode.childnod
One thing that I would like to point out is how complicated code can be to create things like table rows. Especially when they contain a non-trivial amount of elements (e.g., some # of cells, with input fields, and checkboxes, and buttons, and forms, etc.).
You might want to consider creating a "hidden" table that contains 1 row just as you would like it to be created. Then, you can use the cloneNode() method to duplicate this reference row. Then, you can change the particular elements in question (e.g., attributes) that need to be unique for this actual row.
Then, all you have to do is insert this newly created row duplicate into the table at the appropriate place.
Oh, if all you want to do is hide the containing div, then you need to:
- locate the div in question
- change the "style" attribute to display='none'
Given that we have a button in the "particular row" in question, how do we find the "appropriate" contained div?
- We could use one of the following techniques:
- Have an id that identifies this div within a row (not unique within the document)
Unfortunately, this is considered a "bad practice" since id attributes are supposed to be
unique to the document
- Have a name attribute for this div within the row. This is acceptable, since name attributes
do not have to be unique within the document.
- We could "hard code" the relative location of the div within the TR (this is not a good idea, since it doesn't allow us to change the row contents easily, or reuse the code)
- or we could traverse the DOM hierarchy, looking for something of note, e.g., the div with a particular className
What do you think?
Well, I think that is great but, the new row/form if cloned will clone the users current work in the row being cloned too...right? When the user creates a new row the form should be empty. If we can do it like that and have a starting (empty form object) then great lets do it. I understand what your saying though. Show me the way....i am close to grasping your reasoning i think.
Well, the "lengthy duplication of AddRow code" is certainly not a "best practice".
It is also confusing, and error prone. Other than that, it is fine. :-) (Well, maybe
not "fine", perhaps "adequate").
Anyway, you get to choose. What make the most sense to you. Please remember
though. It's your code, and if it doesn't make sense to you now, think how hard
it will be to change, fix, or reuse it 6 months from now.
Given that we have a button in the "particular row" in question, how do we find the "appropriate" contained div?
- We could use one of the following techniques:
- Have an id that identifies this div within a row (not unique within the document)
Unfortunately, this is considered a "bad practice" since id attributes are supposed to be
unique to the document
- Have a name attribute for this div within the row. This is acceptable, since name attributes
do not have to be unique within the document.
- We could "hard code" the relative location of the div within the TR (this is not a good idea, since it doesn't allow us to change the row contents easily, or reuse the code)
- or we could traverse the DOM hierarchy, looking for something of note, e.g., the div with a particular className
What do you think?
Option3:
- Have a name attribute for this div within the row. This is acceptable, since name attributes
do not have to be unique within the document.
ok, what should the row HTML look like?
How close is this?
<tr>
<td valign='top'>
<div id='mainDiv' class='mainDiv'>
<div id='RowName' class='divRowName'>
</div>
<div id='DivCtrls' class='divCtrls'>
<input type='button' ...>
<input type='button' ...>
<input type='button' ...>
</div>
<div id='DivContent' class='divContentOn'>
<form id='Form2' methoc='POST' action='#'>
<input type='text' name=?? size='40' value='Content #'>
</form>
</div>
</div>
</td>
</tr>
To answer your most recent question, yes.
However, to be more specific, you probably want to retrieve the innerHTML text from the reference (hidden) table, massage the contents to change the "inputName#" and "Content #' text to be specific to the row being added, and then save this in the row.innerHTML of the newly created row.
How does that sound?
Ah to answer your questions:
Q: So you wanna create a template div element to be cloned. We use the doc.getElemBID reference to fetch from a common place each time?
A: Correct.
Q: And in "massaging" the content...wen the row is deleted and the subsequent rows reordered..would we not just pass rowNum as the unique "ID" + rownum?
A: Well, since you are taking about reordering the rows, the "row number" that would be retrieved by the rowNum() routine is a relative row number as it currently exists in the table.
The row number to which you are referring would be a unique, never changing identification of a row number as it was created. Otherwise, we would have to massage the row number information in each row after any table manipulation (e.g., row creation, deletion, or reordering).
This would be difficult, and non-productive. In my opinion, it would be better to have some other name of this concept (other than row number) that can be generated when a row is created, and is never changed thereafter. Then, regardless of the position of this row in the table, the attribute will continue to have this unique value. Hopefully this makes sense.
Q: at the time of render the unique number becomes static doesnt it
A: Well, this is certainly one way to do it. For example, we could have a global variable that contains a "last used value". When we need to create a new row, we simply increment this global value, and use in to create unique id attributes for the row elements.
Q: at the time of render the unique number becomes static doesnt it
A: Well, this is certainly one way to do it. For example, we could have a global variable that contains a "last used value". When we need to create a new row, we simply increment this global value, and use in to create unique id attributes for the row elements.
AND:True true, like the previous rows NUM. Since after reorder it gets a new value, we get reference one and +1 to our current rows IDs. That would guarantee that we are naming current row correctly. Would require a slight modifcation to the :
function thisRowsPreviousSibling( obj ) {
}
Man, we are outside the box now aren't we? Personally, at this point you probably have bertter instincts than mine. You choose. As long as each new tables rows, doesnt get hung on a previous tables IDs, Im A-ok with it.
I think that you saw my gentle nudge.
What we need is some mechanism to generate a unique value to be used to identify table elements (rows, cells, contents, etc).
These unique id attributes could then be used to quickly, and easily locate associated elements that make use of the same unique value. For example, when we create a new row, get generate a new "unique" suffix that will be appended to each of the element values that we will need to reference. For example, ones that come to mind include:
- tr
- input
- div
- form
In our template row (see http://www.experts-exchang
we can refer to this suffix by some special notation (e.g., '<#>' or something).
Then, once we retrieve the innerHTML as a string, we only need to use the string replace call (http://www.w3schools.com/
So, the code to add a new row would become almost trivial:
- locate template TR text
var temp = document.getElementById( 'template' );
if ( temp ) {
var nextRowText = temp.innerHTML;
} else {
alert( 'Sever error - required row template not found.' );
}
- generate a new unique value
- change the template string to replace the "special text" with the new unique value
- determine where the row should be placed (e.g., rowNum)
var row = insertRow( rowNum );
- Assign the row contents using:
row.innerHTML = nextRowText;
sounds easy, doesn't it?
You go HG! I see it coming togeather. I see the area that is runTiming as well.
tbl. not inscope I dont think in that add function, the first time you call it. At least I can't find it in a global before this line:
var row = tbl.insertRow( -1 );
I could be wrong though. And, just a Q... would innerHTML not take the place of ".replace()"? I have used that before and it always seems to automatically replace the content it is callled into. I might be doin it wrong though.
Oh I see. You gonna try find the all the ### and replace them. Hmmm....ok. I think I got my brain around it. Let me take a little break (getting off work now). I will be back on after my daily life duties are completed. Gussy (best pug in the universe) needs to go out and get some "squeaky mouse" time. He the only one that howls for me when I come home at EOD.
Then dinner with the Girlfriend. Thank you for sticking with me on this. This some advanced stuff for me and no one here to help. Thanks HG...see you in a little while.
I'm banging my head on an apparent IE "feature".. specifically:
http://www.thescripts.com/
i.e., IE doesn't like insertRow() :-(
So, I'm trying to figure how how best to work through this.
btw, we too have a pug. Unfortunately, the pug gets to sleep closer to my bride than I do... :-)
You know Im wondering if we couldnt take a little different approach. I mean we are trying to make the addCurrentRow a public function. What if:
-we take the (INPUT_NAME_PREFIX + iteration) out of our table elements, I mean if we remove the private function dependencies we could just create all the row elements outside of the function as a global set of elements, Wrap them up in easily appendable object and call maybe a special case of (addRow())
(if(this.button.id=="ah") add current row)) } else {if(button.id=="addAnother
What you think? We still remove that extra code, we track rows easier and we get to use (this.dTable) as our table reference.
Just trying to think of other possible good work arounds. We would alleviate the (insertRow) problem you are having with IE/NN too.
Maybe?
Found this little guy on the net:
http://www.quirksmode.org/
Look at the way they append. Works in IE and NN too.
A variation of this maybe?
var newTR= tbl.row(0).cloneNode(true)
newTR.id = '';
newTR.style.display = 'block'; <-- because it would have been and set to none to begin with
var newTRs = newTR.childNodes;
for (var i=0;i<newTRs.length;i++) {
var theName = newTRs[i].name
if (theName)
newTRs[i].name = theName + counter;
}
var insertHere = this.row;
insertHere.parentNode.inse
whew... Good morning to you too.
I hadn't reviewed the page of QuirksMode recently. Thanks for the link.
The trouble that I'm currently having though is with FF. It doesn't want to recognize the duplicated '+/-' and 'ah' buttons as real buttons. They display fine, but just don't react
to 'onclick' (sigh).
reading...
Um, lemme find it again...was talking about extending form elements and why radio buttons would not work when cloned. Then said the work around was to (innerHTML) the radio buttons and they work just fine. Another said that certain form elements all had to have unique IDs too if cloned to work properly. Hold on let me find it...
Yep , QM.
"Problems in Explorer
Unfortunately there are two serious problems in Explorer Windows:
First of all it sees all generated radio buttons as belonging to one single array, even if they have different names. Thus the user can select only one radio button in all generated fields. Basically this means that you cannot use radio buttons at all in generated forms.
A reader said that generating radio buttons through innerHTML works fine. If you must use radio buttons, you might try this approach.
Secondly the generated form fields are unreachable by a traditional document.forms call: Explorer simply doesn't enter them in the arrays. This can be worked around by giving the form field an ID and then using getElementById()."
Ahh, ya in quarks mode the actual remove button on their for is first created as a static button in a display:none table/form. They clone it from the static button and it preserves the button function. Cant clone a JS GENERATED button, but can clone static.
<div id="dltBttnTemp">
<input type="button" value="Delete"
onclick="this.parentNode.p
</div>
Ok got it check this out. I made a DIV.ID="buttonTemplate" with display none and set it in the page jsut above the create table button. In that is a button with a hardCoded onclick function. I call the button into the original form creation. I then clone it and the function works. You can clone as many times as you want too. Basically you just have to have the original source of the button come from static. My target for the delete function is wrong but the fucntion fires everytime!!
Code:
I meant on the clone evt. could we take the function, turn it into obj.evt and place it into the button as a new onclick each time. Looks like it's unnec at this point though. Now that we can just access the parentNode strcuture from the static button, will we still need the (deleteRow()) function now?
Also, I notice that once we clone the hidden row, every clone after that takes the place of (row[1]). The hidden row gets pushed to the bttom of the row index. This means that the new first row[1] is getting cloned with whatever was inside it cloned too. We need to always clone the hidden row. How we do that?
The question posed here (http://www.experts-exchan
is basically the same one I asked way back here (http://www.experts-exchan
If I understand correctly, you are looking for the "DivContent" within the current row to be "hidden".
General case code would make use of a getElementsByClassName() routine
(e.g., something like http://javascript.about.co
If found, change the classname accordingly.
Ya, we could do that. We could also use (getELementByName). It returns as a collection too and as long as your (name="") is paired with an exact matching (id="") then it works in IE too.
So you saying identify the content div by putting a name on it. However, does this walk through only the elements in the TR, or the whole document? I'm guessing we are going to do (tr.getElementByName('cont
Show me the way. :)
Almost there...I can make the row disappear now. What you think about this for the hide:
function hideRow(obj)
{
var newTR = thisRow( obj, 'TR' );
if ( newTR ) {
var newTRs = newTR.childNodes;
for (var i=0;i<newTRs.length;i++) {
var cName = newTRs[i];
if (cName)
newTRs[i].style.display = 'none';
}
}
}
ok, its cause:
(var newTRs = newTR.childNodes)
is only returning the single cell from within the TR, gotta get to that next set chilNodes for the cell. THen I think I can use something like (newTRs[i].items(3).style.
Where you at HG? Im gonna write a new web browser if you don't hurry! :)
Yep sure enough, got the content to hide now, still not sure this is the best way since I am using an elements position as the target. I created a new thisCell function, just like (thisRow), then I passed it into the hide function like so:
function thisCell( obj ) {
var td = obj;
while ( td && td.nodeName != 'TD' ) {
td = td.parentNode;
}
return td;
}
function hideRow(obj)
{
var newCell = thisCell( obj, 'TD' );
if ( newCell ) {
var newCells = newCell.childNodes;
for (var i=0;i<newCells.length;i++)
var cName = newCells[i];
if (cName)
//alert(cName.childNodes.l
cName.childNodes[2].style.
}
}
}
And we have TOGGLE!!! So far we 100% cross browser too!!
Code:
function hideRow(obj)
{
var newCell = thisCell( obj, 'TD' );
if ( newCell ) {
var newCells = newCell.childNodes;
for (var i=0;i<newCells.length;i++)
var cName = newCells[i];
if (cName.childNodes[2].class
cName.childNodes[2].classN
} else {
cName.childNodes[2].classN
}
//alert(cName.childNodes.l
//cName.childNodes[2].styl
}
}
}
Ok, here is the cleaned up code a little bit. And by no coincidence do see that we have useful functions left:
function insertRows(rowObjArray)
{
for (var i=0; i<rowObjArray.length; i++) {
var rIndex = rowObjArray[i].sectionRowI
rowObjArray[i].parentNode.
}
}
function reorderRows(tbl, startingIndex)
{
if (tbl.rows[startingIndex]) {
var count = startingIndex + ROW_BASE +1;
for (var i=startingIndex; i<tbl.rows.length; i++) {
count++;
}
}
}
Ok HG, you gonna like this. Went ahead and tidy'd up some more, corrected the CSS and removed that extra <form> space by setting the form display to (dislay:inline), adjusted the top position by 5px, and the bottom-margin:5px, to account.
Results: No vertical gap between content and row controls. Solid in all 4 browsers. Peruse this:
Thanks for the compliments, and interactive/iterative interchange.
Sorry for being away for awhile, I had stuff I had to do yesterday, and wasn't feeling too well.
Unfortunately, the code isn't quite perfect.
Using FF:
- Click "Create New Window" button
- Click on the "Add Another Ctierie" [which continues to be misspelled :-)]
- Click the "ah" button, and we get the following.
Note how the "New Window" row is no longer at the top of the table
Oh, haha. HG, Its all done man. I finished rest of it. Some even more disturbing problems than that one, which I fixed, btw. Were that when you cloned the form elements, the onChange events still had a problem in IE6 (only).
I worked around it by cloning and then grabbing a fresh copy of the form each time. I added quite a lot of things actually. You gave me the missing pieces and I was able to run with it. Thank you!!
Other new features are:
-if row open, edit button is gone and a new (add) button appears at the bottom of the row. Only one or the other will be shown. (You will see)
-Make sure that after clone, the row is always open...even if it was closed when cloned.
However, I am still having a slight issue.
I have set a piece of code int the delete function to track if the row is the last row, and not DELETE it if it is. You had formally had it there to return an error if the parent element was not a TR. When I use a normal addRow function the catch works perfectly. However if I addCurentRow(), it doesnt check and the table can be emptied completely. Take a look? Here is the latest. And yes, it Cross-Browser across the board.
Also, I went ahead and (redout) the images I had replaced the buttons with. So thats why they red and ugly. :)
Some not so great things were of course how I am targeting the (edit) button. Had to put a simple sniffer in, since NN saw that childNode as (1) and IE saw the node as (0).
function hideRow(obj)
{
var newCell = thisCell( obj, 'TD' );
if ( newCell ) {
var newCells = newCell.childNodes;
for (var i=0;i<newCells.length;i++)
var cName = newCells[i];
if (cName.childNodes[2].class
cName.childNodes[2].classN
if(document.all){ //IE sees the (edit button) as [0] in the collection
cName.childNodes[1].firstC
} else { //FF sees the (edit button) as [1] in the collection
cName.childNodes[1].firstC
}
} else {
cName.childNodes[2].classN
if(document.all){
cName.childNodes[1].firstC
} else {
cName.childNodes[1].firstC
}
}
}
}
}
"... However if I addCurentRow(), it doesnt check and the table can be emptied completely. .."
Ok, at what do you want me to look?
Extra notes:
- It is best if you have a DOCTYPE tag at the beginning of your document (i.e., add the following line before the <html> tag):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html
- It is also better to use the type attribute on the script tags instead of Language. So change from:
<script language="JavaScript" src="drillDowns.js"/></scr
To:
<script type="text/javascript" src="drillDowns.js"/></scr
How to return those DOM objects like (tr), (td), (node)... that was hard. If you hadn;t shown me th light on that I would never have got it working. The cloning difficulties were annoying but workable. I still have 2 functions that we didnt really use, but I am not getting rid of them as I may need them soon, actually.
If you see some ways to fine tune, make better, etc...please feel free to show me. I am liking this dynamic technique of JS alot, Forces you to be good DOM programer really. Would like to use a little simpler targeting with (getSomething) since the (childNode.firstChild...) thing gets a little hairy. But overall I am happy and understand a great deal now.
by the way, you were somewhat correct in your earlier update:
http://www.experts-exchang
except "long running thread" would generally be considered with respect to time (i.e., for how many days a question continues to get updates).
However, with > 200 updates this certainly has been a "busy" thread, especially with only you and I posting
"... However if I addCurentRow(), it doesnt check and the table can be emptied completely. .."
Ok, at what do you want me to look?
1. Go ahead and create a table. Then try to delete that first row. You will get an error, which you should.
2. Now use the ("ah") to create a row. Now when you delete all the rows the error wont fire. How come?
regarding your recent update:
http://www.experts-exchang
generally it is better if the question is better targeted. As you have seen, we have been over a number of items, and I'm quite certain that few people (other than you and I) are actually reading the question because of the number of updates. Most people don't have the patients to wade through this many updates. They would prefer a question with a small number of "on topic" updates/responses to point out the solution.
However, I'm just here to share some of my knowledge, and if that takes > 200 updates, that's fine.
Haha, ya but, you taught me. You didnt just a give a hungry man a sandwich...you taught him how to farm. I feel extremely lucky and thank you again. I mean you would think EE could change the model a little bit for lessons. You know, Expert realizes that the person is low in some DOM knowledge and techniques.... "I see your low...want lessons?" Lessons could be worth more $$$ to the expert too!!
Just a thought. :) Lunch, be back in like 1hr.
Ok, yes, you got the alert. The alert only happens if you are trying to remove a row that was added with the private (addRow()) function.
However, if you use the (addCurrentRow()) public function, to add a row, and then start deleting the rows, you will NOT see that alert, and it WILL delete all the rows in the table. The goal was to always have one row still in the table.
So, that is perplexing me.
Hmmm....SHouldnt be a hidden row. THere was one but I removed it. Now it just grabs everything from the Template and uses taht as the clone. Right? Hmmm.....I mean if you turn the (form template) on to show, it appears before the first row but, its not technically in the table.... or at least it shouldnt be.
Try this in your delete function and then use "ah" and watch. It actually shows 2 rows as a total of (4) once you add an additional row with ("ah"). Weird:
//Role: delete the current row
function deleteCurrentRow( obj )
{
var tbl = thisNode( obj, 'TABLE' );
var tblRows = tbl.rows.length;
if ( tbl && tblRows > 4) {
tbl.deleteRow( rowNum( obj ) );
alert(tblRows)
} else {
alert(tblRows)
alert( 'You cannot Delete the Last Row.' );
}
}
We need to tell (rowNum) to decrease the row count by 1. after a clone the row count goes from 3 to 5. After one row is removed the row Count still shows 4, making the condition pass. So, we are (or maybe) I am increasing the rowCount on (addCurrentRow) by +1 when I use the function. I can't seem the find where though.
Hmmm.
ok, so we could have the loop be something like:
var info = '';
for ( var i = 0; i < tbl.rows.length; i++ ) {
var row = tbl.rows[ i ];
var name = row.getAttribute( 'name' );
var id = row.getAttribute( 'id' );
info += 'row[ ' + i + '] name = "' + name + '" id = "' + id + '"\n';
}
alert( 'Row info:\n' + info );
FOUND IT!!! We werent using the actual rows.length. Works like a champ now. :)
function addCurrentRow( obj )
{
counter = 0;
var tbl = thisNode( obj, 'TABLE' );
//var row = tbl.insertRow( -1 ); //<-- WAS
var row = tbl.rows.length; //<-- CHANGED TO THIS.
var num = rowNum( row );
if ( tbl ) {
num = rowNum( obj ) -1;
var newTR= tbl.rows[1].cloneNode(true
newTR.style.display = '';
var newTRs = newTR.childNodes;
And your right, about the row count. THe ID is that at the time of creation. Which brings me to my recurring point about the (reorder()) function. We could rewrite those guys to be the actual (row index) numbers. Especially since we arent (IDs) to find and control our row elements. We arent dependent on the iterator for that.
Means if we run (reorder) after an (addCurrent) we could always use 0 as the base rowCount for any further indexing. Not sure what that would gain us but, it seems to be mathematically symmetrical.
Thanks on the spelling, fixed.
On the criteria RE: we do, we can pass the actual row index of the row as the (reordered) value. Then all the rows ID and NAMES would match the actual row index of that row.
Wouldn't it? Maybe not...I will have to try that one. Again, I'm not sure what it would gain me. Ever have something stick in your mind as good thing, but your not sure why yet? Thats what happening. I think I got some side processes in the brain that have compiled something my upper thinking hasn't realized yet. Gotta get those guys talking to each other. Team building exercises? :)
Business Accounts
Answer for Membership
by: dtreadway7Posted on 2008-03-17 at 08:09:26ID: 21142854
Day 4: still no contacts form any experts. It is St. Patty's though so maybe I will get lucky! Here what I got so far. I realize that many problems exist with this table and tracking the rows. I now can correctly add a row. I modified the addRow function and now set the (dTable.rows.length) as my (rows) variable that I pass to get an accurate place of the row at the end of the table, but before the table footer.
Num)). Not working very well though. Any help today? Below is the new code:
The removeRow() function is not so easy though. I am not creating a form element into a fourth cell on the new row, and I am to set a value that is the form value of the current row at the time it is created. I am now trying to access that value for (this.dTable.deleteRow(row
Select allOpen in new window