SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Member
    Join Date
    Oct 2008
    Location
    NC
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Focus &/ Table BG Help Needed

    A representation of a project I'm working on is posted at
    centerproto.zapto.org The statement "January's Birthday" is associated with "today." I'd like to have "today" highlighted in some way when the page is accessed, either by focus or table background color. The focus/color should move with button clicks. You can view the source code on the site. This is a first post for me, so please help with the post format as well as the problem

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Here's a way to do it. I've tidied some things up too, but a further post will go into other tidying up that should be done as well.

    Code html4strict:
    <html> 
    <head> 
    	<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" /> 
    	<link rel="stylesheet" href="CSS/buttonsStyle.css" type="text/css" /> 
    	<title>Help I Hope</title> 
        <style type="text/css"> 
        span.by {
            color:brown;
            font-size: 120%;
        }
        a:focus,
        a:active {
            background-color: gray;
        }
        </style> 
        <script type="text/javascript"> 
        function init() {
        	var el = document.getElementById('show2');
        	el.onclick();
        	el.focus();
        }
        function showdiv($on){  //show
            hidediv();
            document.getElementById($on).style.display = '';
        }
        function hidediv($off){  //hide
        	var i;
        	if ($off) {
        		document.getElementById($off).style.display = 'none';
        	} else {
        		for (i = 1; i <= 3; i += 1) {
        			hidediv(i);
        		}
        	}
        }
        </script> 
    </head> 
    <body text="midnightblue" alink="tomato" vlink="midnightblue" onload="init()"> 
    <div>
    	<table id="myExper" width=190 height=75 border=0>
    		<tr>
    			<td><a id="show1" href="#" onClick="showdiv(1)">yesterday</a></td>
    			<td><a id="show2" href="#" onClick="showdiv(2)">today</a></td>
    			<td><a id="show3" href="#" onClick="showdiv(3)">tomorrow</a></td>
    		</tr>
    	</table>
    </div> 
    <div id="1"> 
    	<span class="by">Wednesday Breakfast</span>
    </div>
    <div id="2"> 
    	<span class="by">January's Birthday!!</span>
    </div> 
    <div id="3"> 
    	<span class="by">Eat in the Kitchen</span>
    </div> 
    </body> 
    </html>
    Last edited by paul_wilkins; Oct 29, 2008 at 16:55.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Member
    Join Date
    Oct 2008
    Location
    NC
    Posts
    24
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Paul, What I know I picked up from reading and knowledgeable people like you. Your solution worked perfectly on FF, Opera, IE, & Flock. I changed the page to reflect your changes. I looked forward to your further recommendations on clean-up. Thanks!

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    The best way to start is with nothing. Just the page as it would be with no css or javascript.

    ID attributes can't start with a number. I'm surprised that the example you've done works because of that. In some environments it won't work at all.

    The links should also point to somewhere useful. We can use the appropriate id attributes of their intended target as a link fragment, so that if there is no javascript, then at least you'll be taken to the appropriate location. This also has flow-on benefits for scripting too.

    We don't need the onclick attributes. They all do the same job that can be performed by just one event handler.

    Further on down, we can say bye bye to the class="by" attribute as well, because every single span has exactly the same class on it. When this occurs, you can set the span style directly from css without needing custom class names.

    I may have misunderstood your need for the "by" class, but if it's not needed then you can do as below. In the example you gave even the span's aren't required either. If they are needed though for some other purpose then please put them back.

    Code html4strict:
    <div>
        <table id="myExper">
            <tr>
                <td><a href="#breakfast">yesterday</a></td>
                <td><a href="#birthday">today</a></td>
                <td><a href="#kitchen">tomorrow</a></td>
            </tr>
        </table>
    </div> 
    <div id="sections">
        <div id="breakfast">Wednesday Breakfast</div>
        <div id="birthday">January's Birthday!!</div> 
        <div id="kitchen">Eat in the Kitchen</div>
    </div>

    The css for the table and the sections are up next.
    Note there is a hidden class, which we'll apply to the different sections to hide them. It's best to not use javascript to fiddle directly with styles, but to instead set and unset class names on the elements.

    Code css:
    #myExper {
        width: 190px;
        height: 75px;
        border: none;
    }
    #myExper a:focus,
    #myExper a:active {
    	background-color: gray;
    }
    #sections div {
        color:brown;
        font-size: 120&#37;;
    }
    .hidden {
    	display: none;
    }

    And now we can focus on the scripting.

    When someone clicks on the table link, we want some special behaviour to occur. When multiple links are involved in a groups situation, it's best to use just the one function to capture the click, make sure that it's an anchor that was clicked on, and pass it to the appropriate location.

    The body tag shouldn't be used to start things when the page begins either. Instead, you can either wait for the page to load by placing the script inside a window.onload function

    Code javascript:
    window.onload = function () {
        ...
    }

    or you can avoid all of that onload hassle and put your script at the bottom of the page, which also happens to be one of the best practices for speeding up your web site.

    Whichever way you choose, here's the script to attach an onclick event handler

    The this keyword can't be used to directly obtain the link that was clicked, because it's the "myExper" div that captured the event, but we can get the element that was clicked from the event object.

    Because the click wasn't necessarily on a link, or even an element in some browsers, we should check that we actually do have an anchor element before progressing with it.

    Code javascript:
    var container = document.getElementById('myExper');
    container.onclick = function (evt) {
        evt = evt || window.event;
        var targ = evt.target || evt.srcElement;
        if (targ.nodeType === 1 && targ.nodeName === 'A') {
            showByReferenceFrom(container, targ);
            return false;
        }
    }

    By returning false, the browser won't try to follow the link that was just clicked.

    Next we want to call the onclick event with a custom target. This allows us to simulate a click on that link when the page loads.

    Code javascript:
    container.onclick({target: linkFromEl(container, 1)});
    function linkFromEl(el, num) {
        return el.getElementsByTagName('a')[num];
    }

    The intention of the above code is to limit the number of things that it needs to know. Information about the container, for example, should be kept to a small discrete area, for easier maintenance.

    When one of the links is clicked, we can take the identifier of the section that we're interested in from the link, and use that to show the section.

    Code javascript:
    function showByReferenceFrom(parentEl, el) {
        hideLinksByReference(parentEl.getElementsByTagName('a'));
        show(linkReference(el));
        el.focus();
    }

    When we hide the links, We'll step through each of them and figure out the intended reference id from the href value. To do that we'll take the existing #name value and chop off the # from the start.

    There are a number of ways to do the chopping. Some people use text.substring(1, text.length) and others use just text.substring(1)
    Me, I like to make it clear what's happening, so I use text.slice(1) which slices off one character from the start.

    Code javascript:
    function hideLinksByReference(els) {
        var newEls = [],
    	el,
            i;
        for (i = 0; i < els.length; i += 1) {
            newEls[i] = linkReference(els[i]);
        }
        hide(newEls);
    }
    function linkReference(el) {
        var id = el.getAttribute('href').slice(1);
        return document.getElementById(id);
    }

    Now we're getting into the functions that do the actual showing and hiding of the elements.

    Code javascript:
    function show(el) {
        removeClass(el, 'hidden');
    }
    function hide(els) {
        var i;
        if (els.length) {
            for (i = 0; i < els.length; i += 1) {
                hide(els[i]);
            }
    	} else {
            addClass(els, 'hidden');
        }
    }

    As you can see, their purpose is to be a useful wrapper for the addClass and removeClass functions. These functions come from http://snipplr.com/view/3561/addclas...lass-hasclass/ and have now become the standard way to work with class names.

    Code javascript:
    function hasClass(ele,cls) {
    	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
    }
     
    function addClass(ele,cls) {
    	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
    }
     
    function removeClass(ele,cls) {
    	if (hasClass(ele,cls)) {
        	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    		ele.className=ele.className.replace(reg,' ');
    	}
    }

    And so in conclusion, here's the full script in case any of it was missed. Don't forget that if you run the script from the head of the page you'll need to wrap it in a window.onload function.

    If you put the script at the bottom of the body then you can just leave it as is.

    Code javascript:
    var container = document.getElementById('myExper');
    container.onclick = function (evt) {
        evt = evt || window.event;
        var targ = evt.target || evt.srcElement;
        if (targ.nodeType === 1 && targ.nodeName === 'A') {
            showByReferenceFrom(container, targ);
            return false;
        }
    }
    container.onclick({target: linkFromEl(container, 1)});
    function linkFromEl(el, num) {
        return el.getElementsByTagName('a')[num];
    }
     
    function showByReferenceFrom(parentEl, el) {
        hideLinksByReference(parentEl.getElementsByTagName('a'));
        show(linkReference(el));
        el.focus();
    }
    function hideLinksByReference(els) {
        var newEls = [],
    	el,
            i;
        for (i = 0; i < els.length; i += 1) {
            newEls[i] = linkReference(els[i]);
        }
        hide(newEls);
    }
    function linkReference(el) {
        var id = el.getAttribute('href').slice(1);
        return document.getElementById(id);
    }
    function show(el) {
        removeClass(el, 'hidden');
    }
    function hide(els) {
        var i;
        if (els.length) {
            for (i = 0; i < els.length; i += 1) {
                hide(els[i]);
            }
    	} else {
            addClass(els, 'hidden');
        }
    }
    function hasClass(ele,cls) {
    	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
    }
     
    function addClass(ele,cls) {
    	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
    }
     
    function removeClass(ele,cls) {
    	if (hasClass(ele,cls)) {
        	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
    		ele.className=ele.className.replace(reg,' ');
    	}
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    I have a correction to make to the above code, which cannot by now be edited.

    Some web browsers don't return the link href as it appears in the code, but instead returns a fully qualified link that's based on the href. Because of this the slice method cannot be used. Instead, the link has to be split around the # symbol so that you can take the piece on the right-hand side of it as the identifier.

    Code javascript:
    // var id = el.getAttribute('href').slice(1);
    var id = el.getAttribute('href').split('#')[1];
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


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
  •