SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 30
  1. #1
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    getElementByClass Display:None

    Am I using this correctly? For some reason it isn't working.
    PHP Code:
    document.getElementByClass('details').style.display='none'
    I'm using getElementByID to show DIVs inline-block, but I want a universal button to hide whichever DIV is displaying, as well.

    Thanks

  2. #2
    SitePoint Wizard
    Join Date
    Dec 2003
    Location
    USA
    Posts
    2,582
    Mentioned
    29 Post(s)
    Tagged
    0 Thread(s)
    There isn't a getElementsByClass function.

    However, you can make one pretty easily.

    Give me a second and I'll give you one you can use.

  3. #3
    SitePoint Wizard
    Join Date
    Dec 2003
    Location
    USA
    Posts
    2,582
    Mentioned
    29 Post(s)
    Tagged
    0 Thread(s)
    Here we go:
    Code:
    /// Returns an array of all elements including and within the element that this function is called from.
    /// If you want only elements with a certain classname and certain tagname, you can supply the optional tagname.
    /// @param name - The name of the class to search for (case-sensitive).
    /// @param tagname - The tag name of the elements you want to get. (optional, case-insensitive).
    Element.prototype.getElementsByClass = function(name, tagname) {	
    	var elements = new Array();
    	
    	if(this == document)
    		var node = document.body;
    	else
    		var node = this;
    	
    	while(node.tagName != 'HTML') {
    		if(node.className) {
    			var classes = node.className.split(' ');
    		
    			for(var i=0; i < classes.length; i++)
    				if(classes[i] == name) {
    					if(!tagname || tagname.toLowerCase() == node.tagName.toLowerCase())
    						elements.push(node);
    					break;
    				}
    		}
    		if(node.hasChildNodes())
    			node = node.firstChild;
    		else if(node.nextSibling != null)
    			node = node.nextSibling;
    		else if(node.parentNode != this && node.parentNode.nextSibling != null)
    			node = node.parentNode.nextSibling;
    		else
    			break;
    	}
    	
    	return elements;
    }
    
    Document.prototype.getElementsByClass = Element.prototype.getElementsByClass;
    You can check out an example of it in action here: http://www.arwebdesign.net/tests/byclass.html

    I added an optional tag name since you said you only wanted divs. If you notice, it is prototyped for both Element and Document, which means you can use it like this:
    Code:
    document.getElementsByClass("bob");
    document.getElementById("someid").getElementsByClass("bob");
    Good luck, let me know if there are any problems.

  4. #4
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow, thanks. I didn't realize it'd be that much code.

    Not that I don't appreciate the work you did, but if there is no such function is it possible/shorter to write one that hides any DIV with an ID in the format "details#" where # is any number?

    Also, all I'm seeing on your example is the following.
    bob1

    bob2

    bob3

    bob4

    bob5

    bob8

    bob9

    Test created by Christian Snodgrass of Azure Ronin Web Design
    Safari 4 b.

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,719
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    You could try it with jQuery

    Code javascript:
    $([id^=details]).hide();

    The ^= matches attributes that start with the given value.
    http://docs.jquery.com/Selectors/att...attributevalue

    The real trick though is how to achieve this without jQuery, using a small amount of code.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm. I don't have a problem using jQuery but as of now I'm not using it, so I'd have to include all the javascript files, right?

  7. #7
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,719
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    You can link to http://jqueryjs.googlecode.com/files...y-1.3.2.min.js which people have quite likely already cached from visiting other pages.

    Code javascript:
    <script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"> </script>
    <script type="text/javascript">
    $(function () {
        $([id^=details]).hide();
    }
    </script>
    Last edited by paul_wilkins; Feb 28, 2009 at 18:57.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  8. #8
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by samanime View Post
    There isn't a getElementsByClass function.

    However, you can make one pretty easily.

    Give me a second and I'll give you one you can use.
    There is a getElementsByClassName function in Firefox 3.*

    Also instead, I would use the Selector API for those browsers that support it.
    Internet Explorer 8, Opera, Safari 3.1, & Firefox 3.1
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  9. #9
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I second logic_earth - I'd use querySelector if it's available and if not just declare a backup method but firstly don't make it a method of the Element prototype because that simply wouldn't work in MS DOM as there is no Element or HTMLElement object.
    Cross browser css bugs

    Dan Schulz you will be missed

  10. #10
    SitePoint Wizard
    Join Date
    Dec 2003
    Location
    USA
    Posts
    2,582
    Mentioned
    29 Post(s)
    Tagged
    0 Thread(s)
    @SoulScratch Oh, you're right. I think I knew that, but just forgot about it when I was getting "creative". To fix this, you would just add another parameter to the function (the object to start at), and change any reference to "this" to the new parameter. I'll update my example function because I don't have not-cross-browser compliant code lingering.

    @geiger Yeah, the demo is just outputting the ids of the elements that it selected to make sure it's correct.

    If you wanted to use older Javascript, the only way to make sure you get all of them is to transverse the tree structure (which is the while loop portion of the code) and manually check the IDs (something like if(substr(node.id,0,7) == 'details') // do something).

    The Selector method is the way to go though if you thing a decent portion of your members will have a relatively up-to-date browser, though be sure to implement a back-up method like what we discussed.

    EDIT: I modified the function so it's now cross-browser compliant.

    Another method you could use to make it shorter is something like:
    Code:
    if(!document.getElementsByTagName)
        return;
    
    var divs = document.getElementsByTagName("DIV");
    
    for(var i=0; i < divs.length; i++)
        if(substr(divs[i].id, 0, 7) == 'details')
            divs[i].style.display = "none";
    That will get all elements with the tag name of "div" and then if they are details#, it'll hide it by setting display:none.

    Hope that helps.

  11. #11
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,719
    Mentioned
    103 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by samanime View Post
    If you wanted to use older Javascript, the only way to make sure you get all of them is to transverse the tree structure (which is the while loop portion of the code) and manually check the IDs (something like if(substr(node.id,0,7) == 'details') // do something).
    If you know that you're going to be dealing with only a cerrtain element, you can use getElementsByTagName quite effectively. Especially if you know that they're contained within some other kind of structure.

    Code javascript:
    var container = document.getElementById('bobContainer');
    var els = container.getElementsByTagName('div');
    var i;
    for (i = 0; i < els.length; i += 1) {
        if (els[i].id.match(/^bob/)) {
            els[i].style.display = 'none';
        }
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  12. #12
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I really don't know Javascript, so I don't understand some of what you all are talking about. I do think still, however, that I'm going about things the wrong way.

    I decided to go ahead and admit access to those who are helping in this thread.
    http://www.myhybridcar.com/fuelecono...ar.php?cid=108
    Username: sitepoint
    Password: temporary

    Click on a tank with a + sign. You'll note a DIV and the table disappear, and a DIV and the appropriate tank DIV appear. The part I'm working on now is the Back to Tank List link. I need to restore the original DIV/table and hide the most recent DIV/DIV.

  13. #13
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, as of now you're relying on adding a hash to the current page, setting divs to inline-block as opposed to block ( the native display method ), and inline JS which could be vastly improved.

    Do this right and it'll work out fine, the first step is to remove all that inline JS and set the ID to the corresponding info div that will popup.

    Step #1: Remove inline JS and add IDs to the table rows in table#data_table, as well as remove the "date" class from the table cells ( and I know you're relying on them for CSS but thats ok we'll modify that as well ).

    Example:

    Code:
    <tr onclick="window.location='#'; document.getElementById('data_table').style.display='none'; document.getElementById('data_heading_left').style.display='none'; document.getElementById('data_details').style.display='inline-block'; document.getElementById('details1953').style.display='inline-block'; " class="data">
    				<td class="data ismore">+</td>
    				<td class="data">February 26, 2006</td>
    				<td class="data">201</td>
    				<td class="data">6.3</td>
    				<td class="data">32.1</td>
    			</tr>
    Becomes

    Code:
    <tr id="row-details1953" class="data">
    				<td class="ismore">+</td>
    				<td>February 26, 2006</td>
    				<td>201</td>
    				<td>6.3</td>
    				<td>32.1</td>
    			</tr>
    Step #2: Modify the two css rules you have for .data, .data_do as such:

    Code:
    .data_do, tr.data, tr.data td {
        border-left:1px solid #CCCCCC;
        cursor:pointer;
        font-size:11px;
        padding:5px 0 5px 7px;
    }
    Also, we'll need to modify .heading_option because we're changing your inline-blocks to regular block ( IE doesnt support inline-block on anything but native inline elements ):

    Code:
    .heading_option {
        margin:-15px 0 0;
    }
    Step #3: Place this JS right before the </body> end tag:

    Code JAVASCRIPT:
    (function() {
        var toggle = function( el, str ) {
    	    if (!str ) {
    		el.style.display = ( el.style.display === '' ) ? 'none' : '';
    	    } else {
    		el.style.display = str;
    	    }
    	},
    	getId = function( id ) { return document.getElementById(id) },
    	table = getId('data_table'),
    	backTo = getId('data_details').getElementsByTagName('a')[0],
    	currentlyOpen,
    	getElementsByClassName = 
    	    document.getElementsByClassName ? function (class_name, scope) {
    		    return (scope || document).getElementsByClassName(class_name);
    	    } 
    	    : document.querySelectorAll ? function (class_name, scope) {
    		    return (scope || document).querySelectorAll("." + class_name);
    	    } 
    	    : document.evaluate ? function (class_name, scope) {
    		    var n,
    			    r = [],
    			    x = document.evaluate("descendant::*[contains(concat(' ', @class, ' '), ' " + class_name + " ')]",
    				    scope || document, null, 5, null);
    		    while (n = x.iterateNext()) {
    			    r.push(n);
    		    }
    		    return r;
    	    } 
    	    : function (class_name, scope) {
    		    scope = scope || document;
    		    var nL = scope.all || scope.getElementsByTagName("*"),
    			    r = [];
    		    for (var i = 0, n; n = nL[i]; ++i) {
    			    if (n.className && (' ' + n.className + ' ').indexOf(' ' + class_name + ' ') != -1) {
    				    r.push(n);
    			    }
    		    }
    		    return r;
    	    };
     
     
        if (!table || !backTo) { return; }
     
        var rows = getElementsByClassName('data', table);
     
        if (!rows.length){return;}
     
        for ( var i = 0, l = rows.length, row; i < l; ++i ) {
    	row = rows[i];
    	row.onclick = function() {
    	    var corresponding = this.id.slice(4);
    	    currentlyOpen = getId(corresponding);
    	    if (!currentlyOpen ) { return false; }
    	    toggle( getId('data_table') );
    	    toggle( getId('data_heading_left') );
    	    toggle( getId('data_details'), 'block' );
    	    toggle( currentlyOpen, 'block' );
    	    return false;
    	}
        }
     
        backTo.onclick = function() {
    	toggle( getId('data_table') );
    	toggle( getId('data_details') );
    	toggle( getId('data_heading_left') );
    	toggle( currentlyOpen );
    	return false;
        }
     
    })();

    Note #1 - I did use a getElementsByClass fn that's more optimized for newer browsers
    Note #2 - For table rows which did not have a corresponding details div ( the ones without plus signs ) clicking does nothing, while currently your page hides the initial table and attempts to show a div. I'm guessing this is because your code is in a php loop, this won't be a problem as my JS does the logic to check if theres a corresponding div.

    Here's my local page on a server, so you can see the changes for yourself:
    http://inimino.org/~amthx/table.html

    Let me know if you have any issues. I only tested the JS if it's added to this page alone, though it shouldn't break if its added globally.
    Cross browser css bugs

    Dan Schulz you will be missed

  14. #14
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hrmm. Thanks, but it doesn't seem to be working very well.
    http://www.myhybridcar.com/fuelecono...ar.php?cid=108

  15. #15
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Could you be more specific? No idea what you're referring to and I see nothing wrong in Fx3 with the JS behavior nor CSS style, it's functioning exactly as I thought it should.
    Cross browser css bugs

    Dan Schulz you will be missed

  16. #16
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay.

    .heading_option no longer displays in the same way, but that's minor.
    Clicking on a row initially works.
    Clicking "back" makes all the columns collapse, ignoring their widths. The tank details also do not disappear; they're at the bottom of the table.
    Clicking a row afterwards makes the columns expand to width instead of the row's expected onclick function.

  17. #17
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Odd, I'm not experiencing the "ignoring their widths" issue at all. The tank details disappear for me in that they're not visible.

    Where are you defining the widths? In the initial row's width attribute for table cell elements?

    What browser are you using? And are you getting any JS errors?

    Did you ctrl+f5 for a hard refresh so the css is updated?

    Edit: This is how it functions in my browser: http://inimino.org/~amthx/js/js.html

    I suspect it may be a JS error causing it to not function correctly or something along those lines...
    Cross browser css bugs

    Dan Schulz you will be missed

  18. #18
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm using Safari 4b Mac, and had similar width problems on Safari 3 Mac. I am referring to the initial width attribute. The problem occurs when they are seemingly ignored and the next cell begins immediately after the previous cell's contents end; there's whitespace at the right of each row.

    Thanks for the screencast—works for you!

    I cleared my cache. No difference.

  19. #19
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey well this is weird. It works when I'm logged out but it breaks again when I'm logged in! Feel free to register to test. (link on the forums page)

  20. #20
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It appears this is left over when you're logged in:

    Code:
    <a href="#" onclick="document.getElementById('data_table').style.display='inline-block'; document.getElementById('data_heading_left').style.display='inline-block'; document.getElementById('data_details').style.display='none'; document.getElementByClass('details').style.display='none';">&lsaquo; Back to Tank List</a>
    This will need to be removed, as there are conflicting onclicks Good job detecting it was the login part.

    And the reason the widths messed up was because you're setting an element which natively acts as a block level but is a table to inline-block, so it loses certain features and apparently column widths are one of them ( from the old JS ).
    Cross browser css bugs

    Dan Schulz you will be missed

  21. #21
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To be honest I don't know what inline-block is. I used it because it was suggested elsewhere. Should I be using inline?

    Regarding the link, removing that Javascript renders the "back" link useless. How does the login affect anything?

    I'm confused

  22. #22
    Guru in training bronze trophy SoulScratch's Avatar
    Join Date
    Apr 2006
    Location
    Maryland
    Posts
    1,838
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The login affects this because it introduces a new element, the Edit anchor and because my code relied strictly on the structure of a non-login page it references the wrong anchor. Therefore the solution is to update this line in my JS:

    Code:
    	    backTo = getId('data_details').getElementsByTagName('a')[0],
    To:

    Code:
    	    backTo = getId('back_to_list'),
    And then edit the HTML for the back button to be as such:

    Code:
    <a href="#" id="back_to_list">&lsaquo; Back to Tank List</a>
    Cross browser css bugs

    Dan Schulz you will be missed

  23. #23
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Fantastic, now it works.

    My heading_option is still appearing a line above "X Tanks" though. How would I fix this?

    Also, what's the difference between inline-block and inline? Why am I using inline-block?

  24. #24
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, when I click on any row the pointer changes back to the arrow until I hover away and back to the table.

  25. #25
    SitePoint Wizard geiger's Avatar
    Join Date
    Jul 2001
    Posts
    2,459
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hrmm couple more things.
    - My .ismore class no longer works.
    - I switched the + indicator with an image and the script no longer knows which rows have more details. How do I get it working again?
    I appreciate your help
    Code JavaScript:
    (function()
    {
    	var toggle=function(el, str)
    	{
    		if (!str)
    		{
    			el.style.display=(el.style.display==='') ? 'none':'';
    		}
    		else
    		{
    			el.style.display str;
    		}
    	},
    	getId=function(id)
    	{
    		return document.getElementById(id)
    	},
    	table=getId('data_table'),
    	backTo=getId('back_to_list'),
    	currentlyOpen,
    	getElementsByClassName=document.getElementsByClassName ? function (class_name, scope)
    	{
    		return (scope || document).getElementsByClassName(class_name);
    	} 
    	: document.querySelectorAll ? function (class_name, scope)
    	{
    		return (scope || document).querySelectorAll("."+class_name);
    	} 
    	: document.evaluate ? function (class_name, scope)
    	{
    		var n,
    		r=[],
    		x=document.evaluate("descendant::*[contains(concat(' ', @class, ' '), ' "+class_name+" ')]",
    		scope || document, null, 5, null);
    		while (n=x.iterateNext())
    		{
    			r.push(n);
    		}
    		return r;
    	} 
    	: function (class_name, scope)
    	{
    		scope=scope || document;
    		var nL=scope.all || scope.getElementsByTagName("*"),
    		r=[];
    		for (var i=0, n; n=nL[i]; ++i)
    		{
    			if (n.className && (' '+n.className+' ').indexOf(' '+class_name+' ') != -1)
    			{
    				r.push(n);
    			}
    		}
    		return r;
    	};
        if (!table || !backTo)
    	{
    		return;
    	}
    	var rows = getElementsByClassName('data', table);
        if (!rows.length)
    	{
    		return;
    	}
    	for (var i=0, l=rows.length, row; i<l; ++i)
    	{
    		row = rows[i];
    		row.onclick=function()
    		{
    			var corresponding=this.id.slice(4);
    			currentlyOpen = getId(corresponding);
    			if (!currentlyOpen)
    			{
    				return false;
    			}
    			toggle(getId('data_table'));
    			toggle(getId('data_heading_left'));
    			toggle(getId('data_details'), 'block');
            	toggle(currentlyOpen, 'block');
            	return false;
    		}
    	}
    	backTo.onclick=function()
    	{
    		toggle(getId('data_table'));
    		toggle(getId('data_details'));
    		toggle(getId('data_heading_left'));
    		toggle(currentlyOpen);
    		return false;
    	}
    })();


Bookmarks

Posting Permissions

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