PDA

View Full Version : JS Change link class on click? (DOM Scripting)



zbbtt
June 15th, 2008, 02:34 PM
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 (http://domscripting.com/domsters/photos.html) from Jeremy Keith's DOM Scripting book/site (http://domscripting.com/) 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[i].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.

ahmednuaman
June 16th, 2008, 05:26 AM
Try:



<a href="bob.html" onclick="this.className = 'selected'">Bob</a>

borrob
June 16th, 2008, 06:13 AM
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').getElementsByTagN ame("LI");
for( i = 0; i < collection.length; i++ )
{
if( !element )
{
// onload select first out of the list
collection[i].className = 't_on';
html = "<img src='" + collection[i].id + "' height='100' width='100'>";
document.getElementById('preview').innerHTML = html;
return;
}
collection[i].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>

zbbtt
June 16th, 2008, 08:07 PM
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!

zbbtt
June 17th, 2008, 10:07 AM
Unfortunately, I still couldn't get this to work. :|
Been looking up and down google for pointers, but no luck so far.
If anyone has any ideas, please let me know.

ahmednuaman
June 17th, 2008, 10:11 AM
Why does it need to be JS? You can use CSS a:visited too!

zbbtt
June 17th, 2008, 11:30 AM
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?

burntdawn
June 17th, 2008, 01:30 PM
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<getEls.length; i++) {
getEls[i].onclick=function() {
for (var x=0; x<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.

zbbtt
June 17th, 2008, 03:37 PM
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!

burntdawn
June 18th, 2008, 03:55 PM
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....

actionAction
June 18th, 2008, 04:29 PM
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

burntdawn
June 19th, 2008, 10:13 AM
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.

zbbtt
June 21st, 2008, 07:42 AM
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.

actionAction
June 21st, 2008, 02:46 PM
My mistake, I thought we were talking about borrob's code!

burntdawn
June 21st, 2008, 05:06 PM
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.

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.

zbbtt
June 24th, 2008, 09:36 AM
I see you got a reply here (http://codingforums.com/showthread.php?p=702426). 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 (http://icant.co.uk/articles/from-dhtml-to-dom/from-dhtml-to-dom-scripting.html) 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.

burntdawn
June 24th, 2008, 03:21 PM
I see you got a reply here (http://codingforums.com/showthread.php?p=702426). Did that solve your problem?

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 (http://icant.co.uk/articles/from-dhtml-to-dom/from-dhtml-to-dom-scripting.html) 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!

zbbtt
June 30th, 2008, 12:04 PM
Yes, please do. I'll try to find more info on this as well (nothing so far).