Jump to content

Creating Table Rows And Columns With Javascript


johnnyg24

Recommended Posts

Can anyone please tell me (or show me) how to created a table with javascript that will produce the following HTML. I need my xml data to be displayed with four columns and two rows. I never know how many pictures and description or which ones will be displayed because it is all decided on by the user. But I do want to control how it is displayed. I need the image description to be located under the image itself and span 4 columns then repeat how ever many times is necessary.I've tried modifying the table rows by using insertRow() and insertCell(), but I can't figure it out. Any help would be much appreciated. Thanks.

<table width="800" cellpadding="0">  <tr>	<td>Img1</td>	<td>Img2</td>	<td>Img3</td>	<td>Img4</td>  </tr>  <tr>	<td>Desc1</td>	<td>Desc2</td>	<td>Desc3</td>	<td>Desc4</td>  </tr><tr>	<td>Img5</td>	<td>Img6</td>	<td>Img7</td>	<td>Img8</td>  </tr>  <tr>	<td>Desc5</td>	<td>Desc6</td>	<td>Desc7</td>	<td>Desc8</td>  </tr></table>etc...

Here is my current function:

function drawTextTableTrial() {	   	var newRow;   			var colorSelect = document.getElementById("colorNumber").value;		   	var classSelect = document.getElementById("classNumber").value;		var styleSelect = document.getElementById("styleNumber").value;		var consSelect = document.getElementById("constructionNumber").value;			   deleteRows(document.getElementById("mainTableBody"));	   for (var i = 0; i < db.length; i++) {			newRow = document.getElementById("mainTableBody").insertRow(i);			if ((db[i].pColorCode == colorSelect && db[i].construction == consSelect && db[i].pClass == classSelect && db[i].pStyle == styleSelect) || (colorSelect == "" && classSelect == "" && styleSelect == "" && consSelect == "") || (colorSelect == "" && classSelect == "" && styleSelect == "" && db[i].construction == consSelect) || (colorSelect == "" && classSelect == "" && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (colorSelect == "" && db[i].pClass == classSelect && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (db[i].pColorCode == colorSelect && classSelect == "" && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (colorSelect == "" && db[i].pClass == classSelect && styleSelect == "" && db[i].construction == consSelect) || (db[i].pColorCode == colorSelect && db[i].pClass == classSelect && styleSelect == "" && db[i].construction == consSelect) || (db[i].pColorCode == colorSelect && classSelect == "" && styleSelect == "" && db[i].construction == consSelect) || (colorSelect == "" && classSelect == "" && db[i].pStyle == styleSelect && consSelect == "") || (colorSelect == "" && db[i].pClass == classSelect && db[i].pStyle == styleSelect && consSelect == "") || (db[i].pColorCode == colorSelect && classSelect == "" && db[i].pStyle == styleSelect && consSelect == "") || (db[i].pColorCode == colorSelect && db[i].pClass == classSelect && db[i].pStyle == styleSelect && consSelect == "") || (colorSelect == "" && db[i].pClass == classSelect && styleSelect == "" && consSelect == "") || (db[i].pColorCode == colorSelect && classSelect == "" && styleSelect == "" && consSelect == "") ||																																																																																																																																																																																																																																																																																																																																																																																																				 (db[i].pColorCode == colorSelect && db[i].pClass == classSelect && styleSelect == "" && consSelect == "")) {						appendCell(newRow, "Desc", db[i].desc);						appendImgCell(newRow, "Image", db[i].skuImg);			}		 }		}						 	  	   function appendImgCell(Trow, Cclass, sImg) {		 var newCell = Trow.insertCell(Trow.cells.length);		 newCell.className = Cclass;		 im = document.createElement("img");		 im.src = sImg;		 im.setAttribute('width', 150);		 im.setAttribute('height', 150);		 newCell.appendChild(im); 	  }		  	  function appendCell(Trow, Cclass, txt) {		 var newCell = Trow.insertCell(Trow.cells.length);		 newCell.className = Cclass;		 newCell.innerHTML = txt;	  }	  function deleteRows(tbl) {		 while (tbl.rows.length > 0) {			tbl.deleteRow(0);		 }	  }

Link to comment
Share on other sites

You need to keep track of 2 rows for the images and text, and add the cells to one or the other. You can use the mod operator to figure out when to create new rows.

for (var i = 0; i < db.length; i++) {			if (i % 4 == 0)			{			  imgRow = document.getElementById("mainTableBody").insertRow(-1);			  txtRow = document.getElementById("mainTableBody").insertRow(-1);			}			...

Link to comment
Share on other sites

I tried taking some of what you said and apply to my function but it displays strange. It looks as though the selections jump all over the table cells. If I am not making myself clear here is the link Search Test Page. Try selecting color Gold/Caramel and you will see what I mean. Also, the images are not displaying. I know it's because of the .innerHTML but I don't know how to convert the xml element into an image. If you could help with that too it would be great. Thanks.

for (var i = 0; i < db.length; i++) {					if (i % 4 == 0)			{			  imgRow = document.getElementById("mainTableBody").insertRow(-1);			  txtRow = document.getElementById("mainTableBody").insertRow(-1);			}											var cellA=imgRow.insertCell(0);				var cellAA=txtRow.insertCell(0);//it then goes through my select statement and does this{																																																																																																																																																																																																																																																																																																																																																																																											cellA.innerHTML=db[i].skuImg;				cellAA.innerHTML=db[i].pColor;			}

Link to comment
Share on other sites

It looks like you're inserting blank cells for some reason. If you're going through a list of things and filtering them, and you find one that doesn't match, it looks like you're inserting a blank cell instead of doing nothing. If you have the image filename, you can use that as the src and write an img tag into the cell.

Link to comment
Share on other sites

Thanks for the image tip. It works great. I am still having trouble with the display aspect. It does look like I am inserting blank cells for the ones that don't pass the if test. What is a good way to remove those items that don't pass the test?

Link to comment
Share on other sites

You don't need to remove anything, you just need an if statement that checks whatever you want to check before it adds a cell. In other words, don't add a cell for every single item, only the ones that pass whatever test you have.

Link to comment
Share on other sites

Please bear with me, I am very new to javascript and still trying to work A LOT of things out. I understand what you are saying about creating the cells after the if statement, not before like I am doing now. I tried putting the if statement before creating the cells but it came back with a blank page: Here is the script, I know it's wrong but I can't figure out why.

function drawTextTableTrial() {				var colorSelect = document.getElementById("colorNumber").value;		   	var classSelect = document.getElementById("classNumber").value;		var styleSelect = document.getElementById("styleNumber").value;		var consSelect = document.getElementById("constructionNumber").value;			deleteRows(document.getElementById("mainTableBody"));	   			for (var i = 0; i < db.length; i++) {											  if ((db[i].pColor == colorSelect && db[i].construction == consSelect && db[i].pClass == classSelect && db[i].pStyle == styleSelect) || (colorSelect == "" && classSelect == "" && styleSelect == "" && consSelect == "") || (colorSelect == "" && classSelect == "" && styleSelect == "" && db[i].construction == consSelect) || (colorSelect == "" && classSelect == "" && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (colorSelect == "" && db[i].pClass == classSelect && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (db[i].pColor == colorSelect && classSelect == "" && db[i].pStyle == styleSelect && db[i].construction == consSelect) || (colorSelect == "" && db[i].pClass == classSelect && styleSelect == "" && db[i].construction == consSelect) || (db[i].pColor == colorSelect && db[i].pClass == classSelect && styleSelect == "" && db[i].construction == consSelect) || (db[i].pColor == colorSelect && classSelect == "" && styleSelect == "" && db[i].construction == consSelect)	|| (colorSelect == "" && classSelect == "" && db[i].pStyle == styleSelect && consSelect == "") || (colorSelect == "" && db[i].pClass == classSelect && db[i].pStyle == styleSelect && consSelect == "") || (db[i].pColor == colorSelect && classSelect == "" && db[i].pStyle == styleSelect && consSelect == "") || (db[i].pColor == colorSelect && db[i].pClass == classSelect && db[i].pStyle == styleSelect && consSelect == "") || (colorSelect == "" && db[i].pClass == classSelect && styleSelect == "" && consSelect == "") || (db[i].pColor == colorSelect && classSelect == "" && styleSelect == "" && consSelect == "") || (db[i].pColor == colorSelect && db[i].pClass == classSelect && db[i].pStyle == styleSelect && db[i].construction == consSelect)) {													if (i % 4 == 0){								  imgRow = document.getElementById("mainTableBody").insertRow(-1);					  txtRow = document.getElementById("mainTableBody").insertRow(-1);										var cellA=imgRow.insertCell(0);								var cellAA=txtRow.insertCell(0);								im = document.createElement("img");				im.src = db[i].skuImg;				im.setAttribute('width', 150);		 		im.setAttribute('height', 150);				cellA.appendChild(im);												lk = document.createElement("a");				lk.href = db[i].skuImg;					lk.innerHTML = db[i].desc;				cellAA.appendChild(lk);			}		 }		}

Link to comment
Share on other sites

OK, the first order of business is to get rid of that massive condition for the if statement. How about this instead:if (db.pColor == colorSelect || db.construction == consSelect || db.pClass == classSelect || db.pStyle == styleSelect)Start with that, and we'll go from there. Second, install Firebug for Firefox to help with testing, it will catch any syntax or runtime errors.

Link to comment
Share on other sites

That was my original if statement and I found that the data it filters is wrong. I think it may be because the user can select from 4 different drop down boxes to really define their search or they can select "All" if they are unsure or don't care about certain search criteria. For example if a customer wants to find a red stripe fabric but doesn't care if it's a print or a woven they have the option to look at every red stripe we carry regardless of the construction. Other customers may want to only look at printed red stripe fabrics. I hope I am making myself clear.With the if statement you recommend the customer that wants just a printed red stripe will get all stripes, all red fabrics and all prints. I test my pages in IE and in the lower left hand corner it usually tells me if there is something wrong. Is that OK or do should I download firefox?

Link to comment
Share on other sites

I understand you'll want to filter more, but lets start with the smaller expression and fine tune it as we go. I'm just trying to simplify the code, there will be a better way than a giant expression for everything.IE has terrible Javascript debugging, it misses a lot of errors and the ones that it manages to catch, it doesn't give you enough information to figure out what or where the error is.

Link to comment
Share on other sites

It's only listing every fourth result, we need to use another counter to keep track of how many have actually been listed. So add this before the for loop starts:var nr = 0;The other line should use nr instead of i:if (nr % 4 == 0){Also close that if statement after those first two lines, the if statement is only to decide if we need to make a new row.

if (nr % 4 == 0){			  imgRow = document.getElementById("mainTableBody").insertRow(-1);  txtRow = document.getElementById("mainTableBody").insertRow(-1);}

Then add a nr++ after the cells get added, to keep track of how many cells have been added. That should bring it to this:

function drawTextTableTrial() {  var colorSelect = document.getElementById("colorNumber").value;  var classSelect = document.getElementById("classNumber").value;  var styleSelect = document.getElementById("styleNumber").value;  var consSelect = document.getElementById("constructionNumber").value;  deleteRows(document.getElementById("mainTableBody"));  var nr = 0;  for (var i = 0; i < db.length; i++)  {	if (db[i].pColor == colorSelect || db[i].construction == consSelect || db[i].pClass == classSelect || db[i].pStyle == styleSelect)	{	  if (nr % 4 == 0){		imgRow = document.getElementById("mainTableBody").insertRow(-1);		txtRow = document.getElementById("mainTableBody").insertRow(-1);	  }	  var cellA=imgRow.insertCell(0);	  var cellAA=txtRow.insertCell(0);	  im = document.createElement("img");	  im.src = db[i].skuImg;	  im.setAttribute('width', 150);	  im.setAttribute('height', 150);	  cellA.appendChild(im);	  lk = document.createElement("a");	  lk.href = db[i].skuImg;	  lk.innerHTML = db[i].desc;	  cellAA.appendChild(lk);	  	  nr++;	}  }}

If that's working, then what's left is to deal with the filtering, that will be a few extra lines.

Link to comment
Share on other sites

YES!!!!!!!!!!It's working. Thanks you so much!Is the nr a counter that is set to zero before we start the loop, then used in the second if statement to set how many cells are required in each row, and at the end is nr++ being used to cycle through the results? I am just trying to learn all this not just copy it.Ok, now for the if statement.

Link to comment
Share on other sites

nr is just a counter to keep track of the total number of cells printed. It gets incremented every time you add a new cell. The only use for knowing how many cells were printed is to know when to start a new row. That's what this does:

	  if (nr % 4 == 0){		imgRow = document.getElementById("mainTableBody").insertRow(-1);		txtRow = document.getElementById("mainTableBody").insertRow(-1);	  }

If you haven't seen that, the mod operator (%) returns the remainder of a division. If you do 6 % 4 you'll get 2, because 6/4 = 1 remainder 2, mod returns the remainder. So nr % 4 will return 0 for every fourth number (you can change the 4 if you want to show a different number per row). i.e.:0 % 4 = 01 % 4 = 12 % 4 = 23 % 4 = 34 % 4 = 05 % 4 = 16 % 4 = 27 % 4 = 38 % 4 = 0etcYou can even use mod to figure out which particular column you're working with in the row. The reason nr starts at 0 is so that the first mod (0 % 4) comes out to zero, which will trigger a new row (the first row). If nr started at one it wouldn't make a new row first, it would just try to add a cell. It wouldn't make a new row until nr was 4 and 4 % 4 == 0. If you did want to start nr at 1, you would just change the mod to make a new row when the remainder is 1 instead of 0, i.e. nr % 4 == 1.After the for loop finishes, nr will be the total number of search results, so you can print that on the page too if you want to show how many there were.For the filtering, the least confusing way will probably be to add a few if statements after the first one to check for specific cases.

	if (db[i].pColor == colorSelect || db[i].construction == consSelect || db[i].pClass == classSelect || db[i].pStyle == styleSelect)	{	  // something matches	  if (colorSelect != "" && db[i].pColor != colorSelect)		continue; // skip it - color doesnt match	  if (consSelect != "" && db[i].construction != consSelect)		continue; // skip it - construction doesnt match	  if (classSelect != "" && db[i].pClass != classSelect) continue; // class doesnt match	  if (styleSelect != "" && db[i].pStyle != styleSelect) continue; // style doesnt match

That's checking that, if a match was found for any criterium, then it will check each one individually if they filled a value for it (if it's not empty) and if it's different than the item we're looking at. The continue statement says to immediately restart the for loop with the next item. In other words, skip the rest of the for loop and start back at the top with the next value of i. Doing something like that is a lot easier for me to understand than a huge expression in the if statement though.

Link to comment
Share on other sites

Ok, so we are using the 'not equal' to instead of the 'equal' to for the additional if statements. It works great. Thanks so much for your help and patients.I have one other question, how involved is it to add a paginating function. I've looked at some that are out there but without knowing what each function is doing or referencing, it is very hard for me to follow how it works. The reason why I ask is because we have over 10,000 product our customers can choose from. You can understand the loading time and scrolling one would have to do if they decided to look at our entire product line.

Link to comment
Share on other sites

Pagination should be pretty easy to do in this case, because you're keeping track of how many things you're looking at. You would keep a variable that says how many to show per page. When nr hits that value, you would break out of the for loop (that's a break statement, instead of continue). The link to show the next page would run a Javascript function (maybe the same one), but it would pass the previous value of i (the last entry that was printed). The for loop would start at that previous value. So that would take care of 'next'. 'Previous' would be a little more complex. The complexity comes from the fact that we're looking at any item that matches anything, even if we decide later not to print it because something else might not match. So for one page, even if we print 30 items, i might go from 0 - 150 looking for those matching 30. So you wouldn't just be able to subtract 30 from i and start there. You would probably have to keep track of where i starts in addition to where it stops.I guess a less-complex, although maybe slower, way would be to just tell it which page to show and how many. When it finds a match, it would check if the match should go on the correct page, and if not it would continue and go to the next one. This would require it to start at the beginning of the list of items for every page, but would be easier to understand. In other words, if you told it to show the 30 items on page 3, it would start at the beginning like it's doing now and just skip the first 60 matches before printing.Figuring out how many total pages there are is another issue - for that you would need to run through the entire list and count how many match, then divide that by the number of items per page.

Link to comment
Share on other sites

The first way does sound like it's above my skill level. If I were to take the second route of telling what page to display and how many, would I tell the function to run until (nr % 30 == 0)? And if I created a next button, would I tell the i counter to start at 31 and go until 60, so on and so forth...

Link to comment
Share on other sites

You would pass the page number to the function, and the number per page could just be a variable in the function.

function drawTextTableTrial(page) {  var per_page = 30;  ...

The function just needs to run until nr == per_page, since nr is the number of results shown. So you would run drawTextTableTrial(1) to show page 1, drawTextTableTrial(2) to show page 2, etc.To know how many to skip, you would probably have to add another counter. The counter would keep track of the number of matches found, not necessarily how many were shown. So after the series of continue statements where it starts over if the match failed, you would add a line to increment the number of matches found, and then another if statement to check if the match goes on the current page. That would probably go something like this, where num_matches starts at 0:

num_matches++;if (num_matches < (page - 1) * per_page)  continue; // match goes on an earlier page

At the end of the loop, after printing the cell, you would add a line to check when to stop.

if (nr == per_page)  break; // stop the loop

Link to comment
Share on other sites

I am able to set how many are shown on a page, but I am confused as to how I create another page. For example if 20 results pass though the if test and I am showing only 10 per page, how do I create another page with the other 10 results? Should I create new HTML pages and each one run the drawTextTableTrial() function? Or do I create a button that deletes the first 10 and shows the next 10 results? Here is what I have so far.

function drawTextTableTrial(page) {		var per_page = 10 // number of items per page		var colorSelect = document.getElementById("colorNumber").value;		   	var classSelect = document.getElementById("classNumber").value;		var styleSelect = document.getElementById("styleNumber").value;		var consSelect = document.getElementById("constructionNumber").value;		var nr = 0;		var num_matches = 0;		deleteRows(document.getElementById("mainTableBody"));			for (var i = 0; i < db.length; i++) {								if (db[i].pColor == colorSelect || db[i].construction == consSelect || db[i].pClass == classSelect || db[i].pStyle == styleSelect) {	// something matches				  				if (colorSelect != "" && db[i].pColor != colorSelect)					continue; // skip it - color doesnt match				  if (consSelect != "" && db[i].construction != consSelect)					continue; // skip it - construction doesnt match				  if (classSelect != "" && db[i].pClass != classSelect) 					continue; // class doesnt match				  if (styleSelect != "" && db[i].pStyle != styleSelect) 					continue; // style doesnt match								  				num_matches++;					if (num_matches < (page - 1) * per_page)						  continue; // match goes on an earlier page						if (nr % 4 == 0){								  imgRow = document.getElementById("mainTableBody").insertRow(-1);					  txtRow = document.getElementById("mainTableBody").insertRow(-1);				}								var cellA=imgRow.insertCell(0);								var cellAA=txtRow.insertCell(0);								im = document.createElement("img");				im.src = db[i].skuImg;				im.setAttribute('width', 150);		 		im.setAttribute('height', 150);				cellA.appendChild(im);												lk = document.createElement("a");				lk.href = db[i].skuImg;					lk.innerHTML = db[i].pColor + " / " + db[i].desc;				lk.setAttribute('class', 'BodyText');				cellAA.appendChild(lk);								nr++								if (nr == per_page)					  break; // stop the loop				}			}					 }

Link to comment
Share on other sites

The next button only needs to remove the rows and get the next set, it doesn't need to link to another page. You could even move the page variable from a function parameter to a global variable, and have the next and previous buttons increment or decrement the page and then call the draw function. e.g.:<a href="javascript:void(0);" onclick="page--; drawTable();">Previous</a><a href="javascript:void(0);" onclick="page++; drawTable();">Next</a>

Link to comment
Share on other sites

Here is how I used what you said. I know its wrong. I just can't seem to wrap my head around the page number. If I know I need 10 pages to hold all my info would I create 10 separate drawTextTableTrial() functions? So the first page would run drawTextTableTrial(1), page two would run drawTextTableTrial(2), etc...? If I am following, we have set a counter 'num_matches' to 0 and if something passes my if statement it will add to this counter. Then is it looking to see if this counter is less than the 'per_page' number and if so, go a head and add it to the current page. At the end of the statement we are telling the function to stop running when we num_matches == per_page. Then we added a next button <a href="java script:void(0);" onclick="page++; drawTable();">Next</a>. Is this saying to increase the a page counter by one and run the drawTable() function? If so I guess I need to set the page counter to 0 (var page = 0;). And what is the :void(0) doing?If I need to create a new drawTextTableTrial() function for ever page, should drawTextTableTrial(2) page counter start at say 21 if 20 is going to be my per_page number?I'm sorry I can't figure this all out and I appreciate all your help, if I can figure this part out I think my page will be complete.for page 1:

function drawTextTableTrial(1) {		var page = 0;		var per_page = 20 // number of items per page		var colorSelect = document.getElementById("colorNumber").value;		   	var classSelect = document.getElementById("classNumber").value;		var styleSelect = document.getElementById("styleNumber").value;		var consSelect = document.getElementById("constructionNumber").value;		var nr = 0;		var num_matches = 0;		deleteRows(document.getElementById("mainTableBody"));			for (var i = 0; i < db.length; i++) {								if (db[i].pColor == colorSelect || db[i].construction == consSelect || db[i].pClass == classSelect || db[i].pStyle == styleSelect) {	// something matches				  				if (colorSelect != "" && db[i].pColor != colorSelect)					continue; // skip it - color doesnt match				  if (consSelect != "" && db[i].construction != consSelect)					continue; // skip it - construction doesnt match				  if (classSelect != "" && db[i].pClass != classSelect) 					continue; // class doesnt match				  if (styleSelect != "" && db[i].pStyle != styleSelect) 					continue; // style doesnt match								  				num_matches++;					if (num_matches < (page - 1) * per_page)						  continue; // match goes on an earlier page						if (nr % 4 == 0){								  imgRow = document.getElementById("mainTableBody").insertRow(-1);					  txtRow = document.getElementById("mainTableBody").insertRow(-1);				}								var cellA=imgRow.insertCell(0);								var cellAA=txtRow.insertCell(0);								im = document.createElement("img");				im.src = db[i].skuImg;				im.setAttribute('width', 150);		 		im.setAttribute('height', 150);				cellA.appendChild(im);												lk = document.createElement("a");				lk.href = db[i].skuImg;					lk.innerHTML = db[i].pColor + " / " + db[i].desc;				lk.setAttribute('class', 'BodyText');				cellAA.appendChild(lk);								nr++								if (nr == per_page)					  break; // stop the loop				}			}					 }

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...