A Beginner Question In Javascript

Discussion in 'JavaScript' started by Sayedtaqui, Feb 17, 2013.

  1. #1
    HI,
    I m new to javascript and I m trying to add one more class to the the fist <li></li> tag however my script isn't working , can sombody please tell me that why its not happening.

    <html>
    <style>
    .active{
        color:#c39;
        font-weight:bold;
        }
    </style>
    </head>
     
    <body>
    <div id="forNav">   
            <ul>
                <li class="first">Home</li>
                <li>About Us</li>
                <li>Contact Us</li>
                <li>Products</li>
            </ul>
    </div>
     
     
    <script>
     
    item1= document.getElementsByClassName("first");
    item1.className= "active";
     
    </script>
     
    </body>
    </html>
    HTML:
    I m trying to add one more class to the first <li> like <li class="first active">Home</li>
    And if that is not possible how do I create another element inside the first <li> like <li class="first"><span class="active">Home</span></li>.
    I tried this.

    item1= document.getElementsByClassName("first");
    item2=document.createElement('span');
    item2.className="active";
    item1.appendChild(item2);
    Code (markup):

     
    Solved! View solution.
    Sayedtaqui, Feb 17, 2013 IP
  2. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #2
    getElements -- PLURAL, returns an array. you should either loop that array hitting all .first on the page, or use a unique ID with getElementsById...

    I generally avoid getElementsByClassName since legacy browsers (old IE) don't support it.

    Also, are you trying to ADD a class or replace it? This:
    className= "active";

    REPLACES it -- so it would no longer be 'first'. className is a string, so to add a new class you'd do:
    className += ' active';

    to ADD that class.

    Though I'm not sure why you're playing with classes so much from Javascript... I mean, there are reasons to do it, but usually that's for goofy interactive crap that makes pages LESS useful.

    But to be fair, I say that about 90%+ of the stuff people use Javascript to do on pages.
     
    deathshadow, Feb 17, 2013 IP
  3. Sayedtaqui

    Sayedtaqui Greenhorn

    Messages:
    46
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    6
    #3
    I tried what you said deathshadow but its not working
    
    <script>
     
    item1= document.getElementByClassName("first");
    item1.className += 'active';
     
    </script>
     
    </body>
    </html>
    Code (markup):

    I also tried doing this but that did not work either.

    
     
    <script>
     
    item1= document.getElementById("forNav");
    list=item1.getElementsByTagName('li');
    list.className= "active";
     
    </script>
     
    
    Code (markup):
    I know in that I m not grabing hold of the first child of <ul> which is the first <li> but how do I do it , can you write this code for me. I actually cannot make changes between <ul></ul> on the site I m working on(its complicated). So have to use javascript to add the class.
     
    Sayedtaqui, Feb 18, 2013 IP
  4. #4
    Again item1 is pointing at a LIST of li, not the li. That's the difference elements makes over element.

    list[0].className would probably work, but only if that's your first class="list" on the page -- which again is why I would NOT be using getElementsByClassName in the first place.

    Honestly, if you want to target the first LI in that menu... Crap, has some stupid DIV around it for nothing too; as if UL isn't a perfectly good block-level container in it's own right. See, the problem here is the markup is crap. The correct solution is to fix the markup... but if you can't for some goofy reason...

    I supposed the safest answer is to walk the DOM -- whitespace may show up so you can't entirely rely on firstchild... so...

    
    var targetDiv = document.getElementById('forNav');
    var targetUL = targetDiv.firstChild;
    while (targetUL && (targetUL.tagName != 'UL')) {
    	targetUL = targetUL.nextSibling;
    }
    if (targetUL) {
    	var targetLI = targetUL.firstChild;
    	while (targetLI && targetLI.tagName != 'LI')) {
    		targetLI = targetLI.nextSibling;
    	}
    	if (targetLI) targetLI.className += ' active';
    }
    
    Code (markup):
    Gah that's ugly... but it would be far more reliable and possibly even faster than playing with getElementsByClassName.... thogh getElementsByTagName may be less code -- then you wouldn't even to worry about the class... that approach would go something like this:

    var targetDIV = document.getElementById('forNav');
    var listLI = targetDIV.getElementsByTagName('li');
    listLI[0].className += 'active';
    
    Code (markup):
    Yeah, that's better than that first approach. Get all LI inside #forNav (just in case .first is used elsewhere on the page) and then target JUST the first LI. (array index 0)

    I think that's what you are missing though about getElements vs. getElement -- the plural one returns an array so you have to index that array as [0] or [1] or [2], etc, etc... in your code LIST is a LIST -- an Array, it doesn't even HAVE a classname property though it's child members certainly would.
     
    deathshadow, Feb 18, 2013 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #5
    Oh, also since you are just adding a class -- should it even be a class??? Classes are for styling so I assume you have CSS control... as such isn't this first-child's job?

    #forNav ul li:first-child {
      color:#F00;
      // or whatever else you are trying to apply
    }
    Code (markup):
    Works IE7/newer, which actually means it's more compatible than getElementsByClassName -- never use Javascript to do CSS' job. If you need to target other children directly, you could use nth-child or sibling selectors (or even a combination of all three!)

    I actually need to read up on selectors a bit now that IE6 support is in the dust. A lot of really useful CSS2 selectors are real-world deployable now.
     
    deathshadow, Feb 18, 2013 IP
  6. Sayedtaqui

    Sayedtaqui Greenhorn

    Messages:
    46
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    6
    #6
    Thanks, you solved the question but let me tell you my goofy reason that why I m doing this. The active class is not only for styling but it would be used in the jquery function. visit: ammasbiryani.com. I m trying to give an effect to the navigation like this http://www.designlunatic.com/demos/css3lavalamp/ , so that the transparent block follows the mouse. So this is the jquery which has been used for this.
    $(document).ready(function () {
     
        var dleft = $('.lavalamp li.active').offset().left - $('.lavalamp').offset().left;
        var dwidth = $('.lavalamp li.active').width() + "px";
       
     
     
        $('.floatr').css({
            "left": dleft+"px",
            "width": dwidth
        });
     
     
        $('li').hover(function(){
     
         
            var left = $(this).offset().left - ($(this).parents('.lavalamp').offset().left + 15);
            var width = $(this).width() + "px";
            var sictranslate = "translate("+left+"px, 0px)";
           
           
            $(this).parent('ul').next('div.floatr').css({
                "width": width,
                "-webkit-transform": sictranslate,
                "-moz-transform": sictranslate
            });
     
        },
     
        function(){
     
            var left = $(this).siblings('li.active').offset().left - ($(this).parents('.lavalamp').offset().left + 15);
            var width = $(this).siblings('li.active').width() + "px";
     
            var sictranslate = "translate("+left+"px, 0px)";
     
            $(this).parent('ul').next('div.floatr').css({
                "width": width,
                "-webkit-transform": sictranslate,
                "-moz-transform": sictranslate
               
            });
           
        }).click(function(){
           
            $(this).siblings('li').removeClass('active');
     
            $(this).addClass('active');
     
            return false;
           
        });
     
    });
     
     
    var targetfirstDiv = document.getElementById('forNav');
    var targetDiv= document.firstChild;
    var targetUL = targetDiv.firstChild;
    while (targetUL && (targetUL.tagName != 'UL')) {
        targetUL = targetUL.nextSibling;
    }
    if (targetUL) {
        var targetLI = targetUL.firstChild;
        while (targetLI && targetLI.tagName != 'LI') {
            targetLI = targetLI.nextSibling;
        }
        if (targetLI) targetLI.className += ' active';
    }
    
    Code (markup):
    and the structure of the html should be like this.

      <div class="lavalamp magenta">
        <ul >
            <li class="active"><a href="">Home</a></li>
            <li><a href="">About</a></li>
            <li><a href="">Blog</a></li>
            <li><a href="">Services</a></li>
            <li><a href="">Portfolio</a></li>
            <li><a href="">Contacts</a></li>
            <li><a href="">Back to Article</a></li>
            <li><a href="">How it Works?</a></li>
        </ul>
            <div class="floatr"></div>
        </div>
    Code (markup):
    This website is on wordpress. and you know wordpress has some of his own classes which you are compled to use. the list items are coming dynamically(php) so I can fiddle with that. I closed Id I could apply to the html was id=forNav. and that <div> was already there I didnt add the extra div.
     
    Sayedtaqui, Feb 18, 2013 IP
  7. Sayedtaqui

    Sayedtaqui Greenhorn

    Messages:
    46
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    6
    #7
    Thanks deathshow, finally I created what I wanted to, all thanks to you. just have a look at the navigation (its not completle yet but still) http://ammasbiryani.com
     
    Sayedtaqui, Feb 18, 2013 IP
  8. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #8
    Those classes it 'compels' you to use is one of the reasons I won't use WP -- their idiotic hardcoded rubbish that doesn't even let the skinner actually skin the blasted thing is at the top of my **** list. If I was in a situation where I had to deal with turdpress, I'd be doing something like this:
    http://www.sitepoint.com/wordpress-menu-html-tidy/

    To gut out all the garbage pointless classes.

    What you are trying to do, I also wouldn't even think of doing on a website in the first place -- some goofy "lava" visual effect helps users in using the page how exactly? If it doesn't actually help and is just some 'gee ain't it neat' animated garbage -- it's not worth a 32k library and then another 2k of scripting on top of that! Admittedly, jquery by itself is almost HALF my ideal size for a page template; that's HTML+CSS+SCRIPTS+IMAGES. (counting content text, not counting content images).

    Don't take this the wrong way -- but you've got an inaccessible fixed width layout, inaccessible fixed metric (px) fonts, gibberish/broken heading orders, and are wasting 1.6 megabytes in 108 files (the latter explaining the 40 second page load time here since my ping time to everywhere SUCKS) to deliver 2k of plaintext and a dozen content images. With an ungodly 29 script files coming to a megabyte uncompressed and around half a meg if compression is enabled -- the LAST thing that page needs is more scripting! In terms of filesizes you've got more scripting than you do IMAGES! The scripting ALONE is ten to twelve times my ideal page target size and five or six times the upper limit I'd allow a normal page like that to reach!

    Though I'm also looking at the page and wondering what the blue blazes it needs 66 images for.

    Laundry list of how not to build a website, though it's EVERYTHING I've come to expect from turdpress, jquery and HTML 3.2 that until recently would have had 4 tranny slapped on it, and now just has 5's lip service around it... Part of why every time someone calls HTML 5 the future I say "really? Looks like 1997 to me!"

    I'd grab 90% of the scripting on that page by the genitalia and rip it out - same for the endless pointless images that don't even seem to be used on the page. Does more to get in the way of the content than to deliver the content. Good frame of mind for visual effects? If you can't do it from the CSS in ten lines or less, don't do it.
     
    Last edited: Feb 18, 2013
    deathshadow, Feb 18, 2013 IP
    ryan_uk likes this.
  9. Sayedtaqui

    Sayedtaqui Greenhorn

    Messages:
    46
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    6
    #9
    I got the point, and I agree with you. I would remove that from the website and I m also now planning to move it from wordpress. and I have one more question on your forum, waiting for your reply. http://techtalkin.com/Thread-Overriding-height-coming-from-script . your suggestions are most welcome deathshadow but I m looking for a solution , if you could please tell me.
     
    Sayedtaqui, Feb 18, 2013 IP
  10. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #10
    I replied there, I also moved it to website and development since you put it in the help section for the FORUMS, not the help me with my site area.

    NOT that it's my site -- I'm just prolific over there.
     
    deathshadow, Feb 18, 2013 IP