Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    Regular Coder
    Join Date
    Jan 2006
    Posts
    377
    Thanks
    8
    Thanked 1 Time in 1 Post

    Select similar elements with DOM

    Hi,

    I have similar blocks on the webpage. They are actually tables with same class.

    Code:
    <table class="default" width="100%" cellspacing="0" cellpadding="0">
    	<tr><th>Block Title</th></tr>
    	<tr><td valign="top">Block content</td></tr>
    </table>
    
    <br style="line-height:10px">
    
    <table class="default" width="100%" cellspacing="0" cellpadding="0">
    	<tr><th>Another Block Title</th></tr>
    	<tr><td valign="top">Another Block content</td></tr>
    </table>
    
    <br style="line-height:10px">
    I would like to select and access these elements by DOM. How can I do this? I can give them an ID but as they are generated, they all will have the same ID and I guess this is not possible.

  • #2
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,274
    Thanks
    28
    Thanked 271 Times in 265 Posts
    Quote Originally Posted by guvenck View Post
    I would like to select and access these elements by DOM. How can I do this?
    Code:
    d = document;
    var tables = d.getElementsByTagName("table");
    If you want to narrow down things by class attribute, you could loop through the tables.

    Code:
    for (var i = 0; i < tables.length; i++) {
    	if (tables[i].hasAttribute("class") && tables[i].getAttribute("class").match(/(^| )default( |$)/)) {
    		// do something
    	}
    }
    Of course, Internet Explorer doesnt support references to class attributes properly, so the less intuitive DOM HTML must be used.

    Code:
    for (var i = 0; i < tables.length; i++) {
    	if (tables[i].className && tables[i].className.match(/(^| )default( |$)/)) {
    		// do something
    	}
    }
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • Users who have thanked Arbitrator for this post:

    guvenck (08-23-2007)

  • #3
    Senior Coder coothead's Avatar
    Join Date
    Jan 2004
    Location
    chertsey, a small town 25 miles south west of london, england.
    Posts
    1,680
    Thanks
    0
    Thanked 230 Times in 225 Posts
    Hi there guvenck,

    you may find this rather unsophisticated but nevertheless mildly amusing...
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    
    <script type="text/javascript">
    window.onload=function() {
    getTable();
    }
    function getTable(){
    
       ta=document.getElementsByTagName('table');
    
    for(c=0;c<ta.length;c++){
    if(ta[c].className=='default') {
    
       th=ta[c].getElementsByTagName('th');
       td=ta[c].getElementsByTagName('td');
    
    for(k=0;k<th.length;k++){
       alert('table number '+(c+1)+'\nth number '+(k+1)+
             ' has this content...\n\n'+th[k].firstChild.nodeValue);
     }
    for(l=0;l<td.length;l++){
       alert('table number '+(c+1)+'\ntd number '+(l+1)+
             ' has this content...\n\n'+td[l].firstChild.nodeValue);
       }
      }
     }
       td[0].firstChild.nodeValue='Lorem ipsum has now been removed';
     }
    </script>
    
    </head>
    <body>
    
    <table class="default" width="100%" cellspacing="0" cellpadding="0">
    <tr><th>Block Title</th></tr>
    <tr><td valign="top">Block content</td></tr>
    </table>
    
    <br style="line-height:10px">
    
    <table class="default" width="100%" cellspacing="0" cellpadding="0">
    <tr><th>Another Block Title</th></tr>
    <tr><td valign="top">Another Block content</td></tr>
    </table>
    
    <br style="line-height:10px">
    <table class="default" width="100%" cellspacing="0" cellpadding="0">
    <tr><th>Lorem Ipsum</th></tr>
    <tr><td valign="top">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin massa. Nam vehicula. 
    Morbi velit nisi, mollis id, ultrices luctus, adipiscing sit amet, lectus. Nunc rhoncus 
    nisl ac enim. Maecenas vestibulum dolor ut velit.</td></tr>
    </table>
    
    </body>
    </html>
    coothead

  • Users who have thanked coothead for this post:

    guvenck (08-23-2007)

  • #4
    Regular Coder
    Join Date
    Jan 2006
    Posts
    377
    Thanks
    8
    Thanked 1 Time in 1 Post
    Thanks to both posts, they are VERY helpful. I think I'll be able to solve my problem this way, thank you very much.

    @Arbitrator:

    Why did you use match() and regular expression rather than className="default"?

  • #5
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,274
    Thanks
    28
    Thanked 271 Times in 265 Posts
    Quote Originally Posted by guvenck View Post
    @Arbitrator:

    Why did you use match() and regular expression rather than className="default"?
    In cases where you have multiple classes assigned to an element, "default" will not match something like class="class1 default class3 class4". If you know for certain that the elements will not have multiple class names, then you can scrap the regular expressions; I dont know how the code will be used, so I wrote the code to be robust just to be safe.
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • #6
    Master Coder
    Join Date
    Feb 2003
    Location
    Ume, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Quote Originally Posted by guvenck View Post
    @Arbitrator:

    Why did you use match() and regular expression rather than className="default"?
    First of all, that'd be className==="default". (Or ==, but I prefer the version that doesn't autocast.)

    Second, he's doing it that way since className is a space separated list or classes, and you may want to use more than one class on the same element. Using regex that way he makes sure the code doesn't break if the element has more than one class.


    Personally I'd use
    Code:
    var
        i=0,
        elm;
    while(elm=tables.item(i++)){
        if(/\bdefault\b/.test(elm.className)){
            // do something
        }
    }
    instead of
    Code:
    for (var i = 0; i < tables.length; i++) {
    	if (tables[i].className && tables[i].className.match(/(^| )default( |$)/)) {
    		// do something
    	}
    }
    for a number of reasons:
    - Code is smaller, simpler, and the syntax stands out more.
    - It caches the element instead of looking it up multiple times.
    - The regex works slightly differently but should do the work unless you have rather uncommon characters in the classes used for your code, and it's easier to see what it does at a glance.
    - The regex just performs a boolean test instead of a match (the results of which were thrown away directly anyway), so it doesn't have to spend time and footprint on creating the array.
    Last edited by liorean; 08-23-2007 at 06:41 PM.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #7
    Regular Coder
    Join Date
    Feb 2005
    Posts
    679
    Thanks
    0
    Thanked 16 Times in 15 Posts
    Quote Originally Posted by liorean View Post
    Personally I'd use
    Code:
    var
        i=0,
        elm;
    while(elm=tables.item(i++)){
        if(/\bdefault\b/.test(elm.className)){
            // do something
        }
    }
    Since i will increment before the conditional, the first table will be missed and the last will not exist
    Code:
    var
        i=0,
        elm;
    while(elm=tables.item(i)){
        if(/\bdefault\b/.test(elm.className)){
            // do something
        }
        i++;
    }

  • #8
    Master Coder
    Join Date
    Feb 2003
    Location
    Ume, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Quote Originally Posted by rwedge View Post
    Since i will increment before the conditional, the first table will be missed and the last will not exist
    Actually, no, that won't happen. The code I posted uses post-increment. That means that first time through the loop, elm will contain tables.item(0), and i will be incremented to 1.

    I should have mentioned though, you use elm instead of tables[i] inside the actual loop. That means you never have to care about what the the value of i is in the loop body at all.

    Also as you can see it uses tables.item in the condition of the loop and doesn't compare to the length of that collection at all. The reason that works is that the condition will return null when you try to access an element that doesn't exist in the collection. In other words, the last table looped over will be the last element in the collection.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #9
    Senior Coder
    Join Date
    Feb 2003
    Posts
    1,665
    Thanks
    0
    Thanked 27 Times in 25 Posts
    Fwiw
    Code:
    function getElementsByClassName(cName,trgtTagName,trgtNode) {
    
    	if (!document.getElementsByTagName) return true;
    
    	var cNameRegEx = new RegExp('(^|\\s)' + cName + '(\\s|$)');
    
    	var tName = trgtTagName || '*';
    	var tNode = trgtNode || document;
    
    	var trgtEls = [];
    	var trgt = 0;
    
    	var els = tNode.getElementsByTagName(tName);
    	for (var i = 0, tEl; tEl = els[i]; i++) {
    		if (tEl.className && tEl.className.match(cNameRegEx)) {
    			trgtEls[trgt] = tEl;
    			trgt++;
    		}
    	}
    
    	return trgtEls;
    
    }
    e.g.
    Code:
    var trgtTables = getElementsByClassName('default','table');
    Last edited by Bill Posters; 08-24-2007 at 11:26 AM.

  • #10
    Regular Coder
    Join Date
    Feb 2005
    Posts
    679
    Thanks
    0
    Thanked 16 Times in 15 Posts
    Quote Originally Posted by liorean View Post
    I should have mentioned though, you use elm instead of tables[i] inside the actual loop. That means you never have to care about what the the value of i is in the loop body at all.
    I was considering the usage of tables[i], thanks for clarifying.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •