Change link class on click? (DOM Scripting)

Hello,

I’ve just started with DOM Scripting… So far, I’m trying to read more about it, but I am also trying to adapt the gallery script from Jeremy Keith’s [URL=“http://domscripting.com/”]DOM Scripting book/site to my own purposes. So far, the image switch works and I’m replacing the alt text of the larger images with the title from the links. But now I need to swap the class of the links once they are clicked, so they become the “selected” link. I’ve tried working it with my very limited knowledge and failed. Maybe you can help me out? Here’s the script:


function showPic(whichpic) {
    if (!document.getElementById("visual")) return true;
    var source = whichpic.getAttribute("href");
    var visual = document.getElementById("visual");
    visual.setAttribute("src",source);
    if (!document.getElementById("visual")) return false;
    if (whichpic.getAttribute("title")) {
        var text = whichpic.getAttribute("title");
    } else {
        var text = "";
    }
    var descricao = document.getElementById("visual");
    if (descricao.getAttribute("alt")) {
        descricao.setAttribute("alt",text);
    }
    return false;
}

function prepareGallery() {
    if (!document.getElementsByTagName) return false;
    if (!document.getElementById) return false;
    if (!document.getElementById("thumb")) return false;
    var gallery = document.getElementById("thumb");
    var links = gallery.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++) {
        links*.onclick = function() {
            return showPic(this);
        }
    }
}

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

addLoadEvent(prepareGallery);

And here’s the links part of the page:


<div id="thumb">
        <!-- LIST -->
        <ul><li class="t_on"><a href="sample_1.jpg" title="Image 1">1</a></li>
        <li class="t_off"><a href="sample_2.jpg" title="Image 2">2</a></li>
        <li class="t_off"><a href="sample_3.jpg" title="Image 3">3</a></li>
        </ul>
</div>

Class t_on is the current/selected image, class t_off is the unselected images. I want to be able to:

  • click a t_off class link and it will change class to t_on, so it becomes selected (visually, the background image of the link changes).
  • as a new link is clicked, the current t_on link becomes class t_off, so it appears as unselected (background image disappears).
  • if i click on a t_on class, it all stays the same, basically.

Since the number of links on each page varies, I want a general purpose function to accomplish this, like the preparegallery function with the for loop. I tried playing around with the code, using className.match and setAttribute with class and the t_on/t_off values, but no dice. Thank you for any help.

here is some code that should help you on your way.
Had to change the href’s because you cannot use a click and a href.

any questions i’ll here from you.


<html>
<head>
<style type="text/css">
.t_on
{
    background-color: red;
}

.t_off
{
    background-color: blue;
}
</style>   
<script type="text/javascript">


function togle_selection( element )
{
    var html;
    var collection = document.getElementById('thumb').getElementsByTagName("LI");
    for( i = 0; i < collection.length; i++ )
    {
        if( !element )
        {
            // onload select first out of the list
            collection*.className = 't_on';
            html = "<img src='" + collection*.id + "' height='100' width='100'>";
            document.getElementById('preview').innerHTML =  html;
            return;
        }
        collection*.className = 't_off';
    }
    element.className='t_on';
    html = "<img src='" + element.id + "' height='100' width='100'>";
    document.getElementById('preview').innerHTML =  html;
}

window.onload = function()
{
    togle_selection( null );
}

</script>
</head>
<body>
<div id="thumb">
    <!-- LIST -->
    <ul>
    <li class="t_on" id='something1.jpg' title="Image 1" onclick="togle_selection( this )">1</li>
    <li class="t_off" id='something2.jpg' title="Image 2" onclick="togle_selection( this )">2</li>
    <li class="t_off" id='something3.jpg' title="Image 3" onclick="togle_selection( this )">3</li>
    </ul>
</div>
<div id="preview">
</div>
</body>
</html>

Hi, thanks for your replies.
I had posted this over at Skill Share and got an advice similar to yours ahmednuaman, but I couldn’t get it to change the class.

I need to do this without inline javascript (and the image href needs to be there for accessibility purposes)… but I’m going to try and use that technique you posted borrob, and see if I can make it work. I’ll be back with hopefully good results! Thanks for taking time to help me out!

Unfortunately, I still couldn’t get this to work. :expressionless:
Been looking up and down google for pointers, but no luck so far.
If anyone has any ideas, please let me know.

I need to show the currently selected link/selected image displayed, so just marking the visited links would not accomplish this and would even add confusion as to which image is currently being displayed. I just need a simple, clean way to do this. But so far, all my efforts have failed. Naturally, the suggestion you posted, with the inline js, works, but I don’t want to use inline js. Just no idea why it doesn’t work within the script with the onclick function.

** I am playing around with it a bit more, and tried setting one of the links with an id (id=“off”) and then added this bit to the showPic function:

    var clicky = document.getElementById("off");
    if (clicky.className = "t_off") {
        clicky.className = "t_on";
    }

And it works, the class is changed. So the problem must be related to how I’m trying to get the class of the links?

I found this posting while looking for an answer to the exact same question. I also am trying to adjust the gallery script from DOM Scripting. I found a function here (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_22992630.html) that I added to the Showpic.js document.

//Creates a selected class when the thumbnail is clicked.

clickMenu = function(menu) {
var getEls = document.getElementById(menu).getElementsByTagName(“li”);
var getAgn = getEls;

for (var i=0; i&lt;getEls.length; i++) {
        getEls*.onclick=function() {
            for (var x=0; x&lt;getAgn.length; x++) {
            getAgn[x].className=getAgn[x].className.replace("selected", "");
            }
            this.className+=" selected";
            }
        }
    }

then I just added the function to my addLoadEvent

addLoadEvent(clickMenu);

and now I have a selected class to use in my style sheet.

I hope this helps.

Hello,

Thank you so much for posting this, it does the trick! I’m not sure if I get the nested for loops… I know what they’re doing (check number of links, put them in a collection/array, then clear the class/assign a new class?), just not sure why it’s done that way. Can anyone explain it? I always like to understand what I’m doing.

Anyway, it’s a relief that it’s working as intended now. Again, thank you very much for your help, and to the previous posters too!

I am trying to understand this as well, so I will post if it starts making sense to me. Please do the same. In the meantime, I am trying to incorporate next/previous buttons into this gallery, but so far no luck. If anyone has any tips…

The code is not using nested for loops, but a conditional (if) within a for loop. It’s doing it this way because this is a logical way. You could use getElementByTagName(‘LI’), but that would get ALL list elements, and you may eventually have some outside of this one part, so it only collects the li elements within the containing div.

The for loop and condition turn off all elements except for the first in the initial loading of the page. The onload event calls the function with null (ie false) to do this. Every other time this function is called (with the onclick event), the for loop simply sets every li classes to “off”, and when it exits the for loop it assigns the function parameter (the list item who’s class you want to change) the “on” class. The li tags are coded to have an id that is the source of the picture. The code at the end gets the source (element.id), makes a variable that is an image tag with the src (element.id) set as the image source, and then assigns that image tag to the innerHTML of the preview div (which basically just replaces the code within the div without reloading the page.

Does that make sense?

Window load = get collection of links, since element is false, set the first link to t_on, insert the image into the preview div, set the rest of the links to t_off

Mouse click = since element is true (it’s an object), set every element to t_off, after that, set the passed in element to t_on and insert the image associated with it into the div

Hope that helps

I added this to my HTML document:

<ul id="buttons">
	<li id="prev"><a href="" >Previous</a></li>
	<li id="next"><a href="" return="false">Next</a></li>
</ul> 

and this to my Javascript document:

// Previous Image Function
prevImage = function() {
	if (!document.getElementById) return false;
	if (!document.getElementById("prev")) return false;

	var prevButton = document.getElementById("prev");
	prevButton.onclick=function() {
		alert("You just pressed the Prev Button");
		}
	}

// Next Image Function
nextImage = function() {
	if (!document.getElementById) return false;
	if (!document.getElementById("next")) return false;

	var nextButton = document.getElementById("next");
	nextButton.onclick=function() {
		alert("You just pressed the next Button");
		}
	}

My alert buttons come up so I am sure those are working. But I am having a lot of trouble replacing those alert statement with working functions.

I want to loop through the gallery links to find out which is the current image and then use that to decrease or increase the image. I’ve tried several different techniques but my javascript is minimal and I think I need to be pointed in the right direction. Any help at all would be appreciated.

I tried looping through the links just like it is done in the Select function I posted on this thread the other day and comparing the className using the match method but I couldn’t get that to work.

The code is not using nested for loops, but a conditional (if) within a for loop.

Thanks for your explanation… but there’s no if used though? Or should that second for be an if?

I want to loop through the gallery links to find out which is the current image and then use that to decrease or increase the image.

Those alerts are a clever way to test it! Will keep that in mind for the future.
What exactly are you doing with the next/previous buttons? Is it a list, eg: < prev 4 5 6 7 next > ?
I tried using match before, but it would break the function. Not sure how to use it properly. Sorry if I’m not of much help… but maybe I can return the favor back and look around for info on this, if I understand what you’re trying to accomplish.

My mistake, I thought we were talking about borrob’s code!

I just want to add the words next and previous (either as text or an image) that will pull up the next or previous image in the gallery. Of course, it also has to then change the class for the link to update which one has been selected. It doesn’t seem like it should be that difficult, but I have spent a ridiculous amount of time on it and can’t seem to get it right. I think I dove into this a little quickly after reading that book, and don’t understand the code well enough yet. I am going to step back and try to get the basics down and then jump back in. In the meantime, if you do figure something out, please let me know! Thank you.

I see you got a reply here. Did that solve your problem?

I know you can use node.previousSibling and node.nextSibling, but I haven’t tried doing anything with them, so I’m not sure. There’s this tutorial page that I’ve found earlier, it explains how to make a next/previous function, but the code was too complex for me to grasp. Maybe you can give it a (rather long) read.

[quote=zbbtt;2348247]I see you got a reply here. Did that solve your problem?
[/quote]
Nope, but I did take a break from this as my head was about to explode.

I know you can use node.previousSibling and node.nextSibling, but I haven’t tried doing anything with them, so I’m not sure. There’s this tutorial page that I’ve found earlier, it explains how to make a next/previous function, but the code was too complex for me to grasp. Maybe you can give it a (rather long) read.

Thanks for the link! I skimmed through and it looks like there is some good information there. I am going to delve in and I’ll hopefully I’ll be able to post a solution soon!

Yes, please do. I’ll try to find more info on this as well (nothing so far).