SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Addict
    Join Date
    Dec 2010
    Posts
    222
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Highlight the active thumbnail in a slideshow

    Hi,

    Here's the slideshow embed code:

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html> 
    <head> 
    <title>Slideshow</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
    #large {width:448px; height:336px; background:#000 url(http://lh5.googleusercontent.com/-ugFamEhbqPo/Thc6hoArbwI/AAAAAAAAABA/PFeHcJhR4Xw/s800/image1.jpg) no-repeat center;}
    #thumbs {padding-top:12px; overflow:auto; white-space:nowrap; width:448px;}
    img {padding:1px; width:80px; height:60px;}
    img:hover {background:#00F;}
    </style>
    </head> 
    <body> 
    <div id="large"></div>  
    <div id="thumbs"> 
    <img src="http://lh3.googleusercontent.com/-hUXeHq5OxEo/Thc7hFFv3gI/AAAAAAAAABQ/Yh7omR8iwzI/s800/thumb1.jpg" alt="" onclick="document.getElementById('large').style.backgroundImage='url(http://lh5.googleusercontent.com/-ugFamEhbqPo/Thc6hoArbwI/AAAAAAAAABA/PFeHcJhR4Xw/s800/image1.jpg)';">  
    <img src="http://lh3.googleusercontent.com/-JU5a-eDnOSg/Thc7g5UkwLI/AAAAAAAAABI/9aCyCMixWb4/s800/thumb2.jpg" alt="" onclick="document.getElementById('large').style.backgroundImage='url(http://lh3.googleusercontent.com/-u5BHGxpr0rg/Thc6hLbDRKI/AAAAAAAAAA8/IvQWzJBvqjg/s800/image2.jpg)';"> 
    <img src="http://lh4.googleusercontent.com/-TdbbNGFbDNk/Thc7g0IBSsI/AAAAAAAAABM/pxpntZaTVoQ/s800/thumb3.jpg" alt="" onclick="document.getElementById('large').style.backgroundImage='url(http://lh4.googleusercontent.com/-4AMWSfi8q7A/Thc6haUv1QI/AAAAAAAAABE/oRdTWawPi_c/s800/image3.jpg)';">
    </div> 
    </body>
    </html>
    I wonder how I can highlight the active thumbnail so its background remains blue until I click another one.
    I also like to avoid the inline JavaScript. Any feedback to improve the coding is appreciated!

    Best regards
    Mike

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,702
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    You can set a class name to the img so that CSS can applied to that class. Typically you remove the class name from all of them, then add it to one of them.

    Before you do that though, let's remove the inline scripting and use a single set of code to achieve the same result.

    The large image needs to be indicated somewhere, so linking to it from within an anchor tag is the standard way that sort of thing is done. Scripting can then take over the onclick event, make use of the image from the link, and then cancel the default behaviour of that link to prevent the web browser from following it.

    Here's how one of the linked images would look:

    Code html4strict:
    <a href="http://www.sitepoint.com/forums/javascript-15/.../image1.jpg"><img src="http://www.sitepoint.com/forums/javascript-15/.../thumb1.jpg" alt=""></a>

    We should use scripting to set up the onclick behaviour. We want to put the script at the bottom of the body.

    Code html4strict:
    <html>
    <head>
    ...
    </head>
    <body>
    ...
    <script src="script.js"></script>
    </body>
    </html>

    The end of the body is the best place to put scripts, because it speeds up the loading of your page, and you can easily work with elements on the page from the script.

    We want to loop through each of the anchor links, and set up an onclick event for each link.

    Code javascript:
    var thumbs = document.getElementById('thumbs'),
    	links = thumbs.getElementsByTagName('a'),
        i;
    for (i = 0; i < links.length; i += 1) {
        links[i].onclick = imageHandler;
    }

    The imageHandler function can access the link via the this keyword:

    Code javascript:
    function imageHandler() {
        var large = document.getElementById('large');
    	large.style.backgroundImage = 'url(' + this.href + ')';
    	return false;
    }

    That now functions as a clickable slideshow, with the added benefit that extra functionality can be added on to things.

    At the end of the imageHandler function, we can add on a call to another function that will deal with the class names.

    Code javascript:
    function imageHandler() {
        ...
    	setActiveLink(this);
    	return false;
    }

    The setActiveLink will loop through all the links removing their class name, and then set a class name of "active" to one of them.

    Code javascript:
    function setActiveLink(link) {
        var links = link.parentNode.getElementsByTagName('a'),
        i;
    	for (i = 0; i < links.length; i += 1) {
    		links[i].className = '';
    	}
    	link.className = 'active';
    }

    You can then use CSS to set the image background of the appropriate active one.

    Code css:
    .active img {
        background:#00F;
    }
    Last edited by paul_wilkins; Jul 10, 2011 at 15:10.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Addict
    Join Date
    Dec 2010
    Posts
    222
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    You can set a class name to the img so that CSS can applied to that class. Typically you remove the class name from all of them, then add it to one of them...
    Comprehensive and educational! Thank you!

  4. #4
    SitePoint Addict
    Join Date
    Dec 2010
    Posts
    222
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    We want to put the script at the bottom of the body.
    Dear Paul,

    If we want to put the script on the head, is it correct coding:

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html> 
    <head> 
    <title>Slideshow</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script type="text/javascript">
    function imageHandler() {
            document.getElementById('large').style.backgroundImage = 'url(' + this.href + ')';
            setActiveLink(this);
    	return false;
    }
    function setActiveLink(link) {
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
            links[i].className = '';
    	}
    	link.className = 'active';
    }
    window.onload = function() {
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
            links[i].onclick = imageHandler;
    }
    }
    </script>
    <style type="text/css">
    #large {width:448px; height:336px; background:#000 url(http://lh5.googleusercontent.com/-ugFamEhbqPo/Thc6hoArbwI/AAAAAAAAABA/PFeHcJhR4Xw/s800/image1.jpg) no-repeat center;}
    #thumbs {padding-top:12px; overflow:auto; white-space:nowrap; width:448px;}
    img {padding:1px; width:80px; height:60px; border:0;}
    a:hover img, a.active img {background:#00F;}
    </style>
    </head> 
    <body> 
    <div id="large"></div>  
    <div id="thumbs"> 
    <a class="active" href="http://lh5.googleusercontent.com/-ugFamEhbqPo/Thc6hoArbwI/AAAAAAAAABA/PFeHcJhR4Xw/s800/image1.jpg"><img src="http://lh3.googleusercontent.com/-hUXeHq5OxEo/Thc7hFFv3gI/AAAAAAAAABQ/Yh7omR8iwzI/s800/thumb1.jpg" alt=""></a>
    <a href="http://lh3.googleusercontent.com/-u5BHGxpr0rg/Thc6hLbDRKI/AAAAAAAAAA8/IvQWzJBvqjg/s800/image2.jpg"><img src="http://lh3.googleusercontent.com/-JU5a-eDnOSg/Thc7g5UkwLI/AAAAAAAAABI/9aCyCMixWb4/s800/thumb2.jpg" alt=""></a>
    <a href="http://lh4.googleusercontent.com/-4AMWSfi8q7A/Thc6haUv1QI/AAAAAAAAABE/oRdTWawPi_c/s800/image3.jpg"><img src="http://lh4.googleusercontent.com/-TdbbNGFbDNk/Thc7g0IBSsI/AAAAAAAAABM/pxpntZaTVoQ/s800/thumb3.jpg" alt=""></a>
    </div>
    </body>
    </html>

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,702
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Rain Lover View Post
    If we want to put the script on the head, is it correct coding:
    JavaScript over the past couple of years has moved to placing scripts at the bottom of the body, for a couple of reasons.

    First, JavaScript blocks the loading of the page, so when scripting it anywhere before the end of the body, page loading stops completely until that script has loaded, been interpreted, and has finished being run by the interpreter. Placing scripts at the end of the body results in the page being seen sooner by people loading the page, which makes the page seem like it's loading faster than it otherwise would with scripts being run from the head section.

    Second, with scripts running from the end of the body, you don't need to use the onload event to trigger and run scripts. Because the DOM above the script is already loaded, scripts at the end of the body have full access to all of the elements on the page, so scripts can work with page elements right away. This means that they don't have to wait for all of the images and other assets to finish loading (as a result of the onload event) before they can start doing their job. This results in the scripts running much sooner than they otherwise would from an onload event, which once again gives a performance improvement to what the user experiences.

    Third, when you want to add other scripts to the page, your onload event is in danger of being clobbered by other scripts that load after it, that may want to use the onload event too. By putting scripts at the end of the body without needing to use any such onload events, your script is capable of running without interference from such issues.

    So yes, while can be correct coding to use an onload event from the head section:

    Code html4strict:
    <html>
    <head>
    <script type="text/javascript" src="script.js"></script>
    </head>
    <body>
    ...
    </body>
    </html>

    Code ="javascript":
    window.onload = function() {
        var links = document.getElementsByTagName('a');
        ...
    };

    There is a much greater benefit in terms of performance and reliability, by running the script directly from the end of the body:

    Code html4strict:
    <html>
    <head>
    </head>
    <body>
    ...
    <script type="text/javascript" src="script.js"></script>
    </body>
    </html>

    Code ="javascript":
    var links = document.getElementsByTagName('a');
    ...
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Addict
    Join Date
    Dec 2010
    Posts
    222
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Thumbs up

    Quote Originally Posted by paul_wilkins View Post
    There is a much greater benefit in terms of performance and reliability, by running the script directly from the end of the body
    Makes perfect sense! From now on I try to practice putting the scripts at the bottom of the body.

    I really appreciate your time and detailed explanations!


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
  •