Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [HTML] How do I make a <table> with scrollbars?

This thread is locked; no one can reply to it. rss feed Print
 1   2   3 
[HTML] How do I make a <table> with scrollbars?
Matthew Leverton
Supreme Loser
January 1999
avatar

I didn't want to confuse him with regular expressions at that point. But yes, your second method is a simpler way to do the same thing.

Your first expression is incorrect though. There's no need to include the dot. And the HTML might have any sort of whitespace separating the class names. Browsers may internally treat them as a single space, but that's not guaranteed.

This is why I wrote:

Quote:

it's handy to create some functions called removeClassName(), hasClassName(), and addClassName().

And the more you start using JS, the more you realize all of these common things have already been packaged nicely into third party libraries. They may add about 35K of overhead, but they remove a lot of headaches and shorten your code up considerably.

Dustin Dettmer
Member #3,935
October 2003
avatar

I was trying to catch stuff like this:

<style>
.link.awesome {
 ...
}
</style>
<a class="link.awesome">...</a>

But the idea is silly anyway. If you're going to parse CSS stuff you should either 1) keep it simple or 2) do the whole thing. You would have to check tag names and a bunch of other stuff to be CSS-ly accurate.

Matthew Leverton
Supreme Loser
January 1999
avatar

But it's written as:

<a class="link awesome">...</a>

Nobody is talking about parsing CSS or HTML—just the className property of elements.

Edgar Reynaldo
Member #8,592
May 2007
avatar

IE's being a gigantic lamer again.

        if (tableheaders.length > 0) {
          var scrolltableheaderdiv = (tables_to_fix<i>.parentNode).insertBefore(document.createElement("div") , tables_to_fix<i>);
          var scrolltableheaderdivtable = scrolltableheaderdiv.appendChild(document.createElement("table"));
          var scrolltableheaderdivtableheader = scrolltableheaderdivtable.appendChild(document.createElement("thead"));
          var headerattributes = tableheaders[0].attributes;
          for (var j = 0 ; j < headerattributes.length ; j++) {
            newattribute = document.createAttribute(headerattributes.item(j).nodeName);
            newattribute.value = headerattributes.item(j).nodeValue;
            scrolltableheaderdivtableheader.setAttributeNode(newattribute);
          }
          scrolltableheaderdivtableheader.innerHTML = column_specs + tableheaders[0].innerHTML;
        }

IE chokes on this line :

            scrolltableheaderdivtableheader.setAttributeNode(newattribute);

and says :
{"name":"594414","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/0\/40926f010225eb04d6bb686c6df55c0c.jpg","w":453,"h":299,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/0\/40926f010225eb04d6bb686c6df55c0c"}594414
So I guess IE7 doesn't recognize the setAttributeNode method?
Does anyone know a suitable replacement?

Also , I ran my page through the The W3C Markup Validation Service and after fixing an extra slash in my dtd and adding a meta tag for document encoding , it tells me the <nobr> tag is invalid , even though it works on SeaMonkey , FireFox , and IE7. I replaced that with CSS for th and td tags using white-space:pre; and that seems to do nicely and the validator gave it the thumbs up.

So any idea what I can do to find a replacement for the setAttributeNode method that will work cross-browsers?

Matthew Leverton
Supreme Loser
January 1999
avatar

I see you like extremely long variable names...

In general, you can just do this:

var div = document.createElement("div");
div.attributeName = value;

And on some occasions (due to quirks in browsers), this version is needed:

var div = document.createElement("div");
div.setAttribute("attributeName", value);

Edgar Reynaldo
Member #8,592
May 2007
avatar

I changed all the attribute setting to use .setAttribute which gives this :

        if (tableheaders.length > 0) {
          var scrolltableheaderdiv = (tables_to_fix<i>.parentNode).insertBefore(document.createElement("div") , tables_to_fix<i>);
          var scrolltableheaderdivtable = scrolltableheaderdiv.appendChild(document.createElement("table"));
          var scrolltableheaderdivtableheader = scrolltableheaderdivtable.appendChild(document.createElement("thead"));
          var headerattributes = tableheaders[0].attributes;
          for (var j = 0 ; j < headerattributes.length ; j++) {
            scrolltableheaderdivtableheader.setAttribute(headerattributes.item(j).nodeName , headerattributes.item(j).nodeValue);
          }
          scrolltableheaderdivtableheader.innerHTML = column_specs + tableheaders[0].innerHTML;
        }

but then IE gives me this in response :
http://www.allegro.cc/files/attachment/594415

and here's line 118 which IE didn't like :

//
          scrolltableheaderdivtableheader.innerHTML = column_specs + tableheaders[0].innerHTML;
//

If I use this to set an attribute then how do I set the attribute's value? :

element.attributeName = section.item(j).nodeName;

Or did you mean that I should say

element."actualattribute" = section.item(j).nodeValue;

where "actualattribute" is a hard-coded string literal?

I don't think this would work :

element.(section.item(j).nodeName) = section.item(j).nodeValue;

All I want to do is to make sure that I pass on whatever attributes the original table's header , footer , and body had on to the new <div><table><thead>/// , <div><table><tbody>/// , <div><table><tfoot>/// elements.

Edit
Maybe I should just be using .childNodes and loop through them using .appendChild?

Matthew Leverton
Supreme Loser
January 1999
avatar

MSDN on innerHTML said:

The property is read/write for all objects except the following, for which it is read-only: COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR. The property has no default value.

Your code is too verbose for me to read. So that may or may not apply to what you are doing. IE won't let you table.innerHTML = "<tr> ..." although you could do something like div.innerHTML = "<table> ... </table>".

In fifty words or less, what is the purpose of your above code snippet?

Edgar Reynaldo
Member #8,592
May 2007
avatar

IE sucks.

My purpose :
Transfer each of the original table's thead , tfoot , and tbody into a new <div><table> for each of them. I want to preserve the attributes of the original table and preserve the attributes of the thead , tfoot , and tbody elements as well.

Matthew Leverton
Supreme Loser
January 1999
avatar

You could do something like:

var t2 = t1.cloneNode(true);

But I don't know why you would need to clone an entire table. It seems to me that (if we are talking about the original subject) all you would have to do is create a second table, remove the THEAD from the original table, and append it to the second table (which would precede the original table in the DOM).

Then resize the table headers to fit the widths of the columns in the original table.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Yes , that would be ideal , I agree.

The problem is that to get proper scrolling in all the browsers , I have to include the table body in a separate <div> with overflow:auto; and a height to get it to scroll properly in all the browsers.

The trouble I run into is that when I have the list of tables to modify , if I use tables_to_fix.getElementsByTagName(thead or tfoot or tbody) then how do I copy that entire element into the new table? Is an element also a node itself? Could I clone it and then use .appendChild(clone) in the new table?

I suppose another option is to get the childNodes of the original table and then filter them into thead , tfoot , and tbody nodes by checking .nodeName so I can use them with .appendChild(). Would I need to clone those then?

Basically , my overall objective is to preserve the original formatting of the entire table through it's transformation into this format :

1<div>
2 <table>
3 <thead>
4 </thead>
5 </table>
6</div>
7<div style="overflow:auto; height:100px;">
8 <table>
9 <tbody>
10 </tbody>
11 </table>
12</div>
13<div>
14 <table>
15 <tfoot>
16 </tfoot>
17 </table>
18</div>

One thing I don't understand though is that a <div> will shrink to fit it's contents vertically , but why not horizontally as well? So I have to set their widths also. Not to mention that SeaMonkey's vertical scroll bars are 15 pixels wide while FireFox and IE's scroll bars are 17 pixels wide.

Edit
Okay , I figured out that getElementsByTagName returns a NodeList of element nodes. Appending a cloned node to the new table is working fine , but there still remains the matter of transferring the attributes of the old table to the new table. The point is that if the original table had CSS , attributes , whatever , I want to preserve that. I realize that I'll have to make some modifications to the table's border frames so that borders don't appear between the table header and body and between the table body and footer but I guess that's the way it goes.

Edit2
Turns out that transferring the attributes of the table wasn't that hard after all. I used

var table_prototype = tables_to_fix<i>.cloneNode(false);
headerdiv.appendChild(table_prototype.cloneNode(true));

and fixed up table_prototype's class attributes to remove the makescroll class.

Now working on setting the column widths among the different div tables using a clone of a new <colgroup> tag that's been set with the different column widths.
Now , how to simply fix up each div table's border frames and margins.

Edit3
From MSDN STYLE reference page

Quote:

Remarks

This attribute is not accessible through scripting. To access styles through scripting, use the style object.

>:( It turns out that IE doesn't support changing an objects inline style attributes through scripting , only through scripting changes in the document's <head> <style> tag's values. Okay , so to jump through the next IE hoop , I have to edit the innerHTML of the <style> tag. :P

Can anyone see what is wrong with these lines? IE says an unknown runtime error happened in the third line.

      var htmlheads = document.getElementsByTagName("head");
      var headstyles = htmlheads[0].getElementsByTagName("style");
      headstyles[0].innerHTML = headstyles[0].innerHTML + ".scrolldiv {\n\r  overflow:auto;\n\r  height:" + tablebodyheight + ";\n\r}";
//

Did I construct the new string incorrectly?

Edit4
MSDN innerHTML reference page
!@#$ .innerHTML is read only for the <style> tag. >:(
So what am I supposed to do to get this to work in IE? Do I have to link in an external style sheet now? W T F ?

What if I copy the innerHTML out of the style tag , alter it , delete the style node and create a new one with the altered innerHTML? Same problem. @#$%.

Okay , the inner HTML is also contained within it's childNode[0].nodeValue of the style node , at least in FireFox it is. So maybe I can clone the node , alter childNode[0].nodeValue of the clone , and then pull a switcheroo. This is really tiresome. It shouldn't take major innovation just to get a table to scroll properly. Maybe I'll email this thread out to W3C and the browsers and see what they think of this crap.

Dustin Dettmer
Member #3,935
October 2003
avatar

Quote:

I don't think this would work :

element.(section.item(j).nodeName) = section.item(j).nodeValue;

These two lines are equivalent.

element.shoes = 'worn';
element['shoes'] = 'worn';

.. and stop using innerHTML. It's a hack that should be avoided at nearly all costs.

There are very few legitimate uses for it.

Edgar Reynaldo
Member #8,592
May 2007
avatar

That doesn't work to set the style attribute of a <div> tag though.

scrolltablebodydiv.style = "overflow:auto; height:" + tablebodyheight + "px;";

In IE7 it tells me 'member not found' for that line.
In SeaMonkey and FireFox it tells me I'm 'setting a property that only has a getter'.

I can set the class attribute of the div but then I have to have the class defined outside of the script and I'd like to have it added to the inline <style> tag of the page , which I have not found a way to do considering the entire <style> tag object is read-only in Internet Explorer. Any suggestions?

Matthew Leverton
Supreme Loser
January 1999
avatar

You have to set the properties individually:

div.style.overflow = "auto";
div.style.height = tablebodyheight + "px";

Any property that has a dash just uses upper case letters. e.g., max-width becomes maxWidth.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Awesome , that did it , even in IE7! Thanks! Now I don't need to mess about with the <style> tag element. Do you know if/how that is possible in IE7?

Matthew Leverton
Supreme Loser
January 1999
avatar

Google on document.styleSheets. There is the standard W3C way and the IE way. It's not widely used though.

bamccaig
Member #7,536
July 2006
avatar

Edgar Reynaldo
Member #8,592
May 2007
avatar

I had to know this wouldn't be as simple as adding in a <colgroup> node to each new table. IE7 decided that when there's a <col width="#px"> tag in a <colgroup> of a table that only the inner section of a <th> or <td> tag should be that wide. Firefox decided that the entire column including padding and border should be that wide. Why can't there just be one !@#$ way to do everything in all the browsers?

Should I just manually set the widths of each and every <th> and <td> tag?

Matthew Leverton
Supreme Loser
January 1999
avatar

Quote:

Should I just manually set the widths of each and every <th> and <td> tag?

Just set the widths on the first row of the tables. (I'm assume there are no colspans.)

 1   2   3 


Go to: