tags:

views:

82

answers:

3

I'm using this code to change opacity when user is on and off a picture unfortunately when the user clicks the image the opacity does not stay at 1. Anyone has an answer ?

$(document).ready(function(){

  $('img#slide').animate({"opacity" : .7})
  $('img#slide').hover(function(){
      $(this).stop().animate({"opacity" : 1})
  }, function(){
      $(this).stop().animate({"opacity" : .7})

  });                


  $('img#slide').click(function(){
    $(this).animate({"opacity" : 1});
  });

});
+2  A: 

You need to somehow disable the mouseleave animation when the user clicks.

A common approach is to add a class, and have the mouseleave check for the existence of the class.

Test the live example: http://jsfiddle.net/KnCmR/

$(document).ready(function () {

    $('img#slide').animate({ "opacity": .7 })

    .hover(function () {
        $(this).stop().animate({ "opacity": 1 })
    }, 
    function () {
        if ( !$(this).hasClass("active") ) {
            $(this).stop().animate({ "opacity": .7 });
        }
    })

    .click(function () {
        $(this).addClass("active");
    });
});

EDIT:

If you want a second click to revert the behavior back to the original, use toggleClass() instead of addClass():

        $(this).toggleClass("active");

jQuery docs:

patrick dw
+1 This method works particularly well in situation where you are controlling more than a single DOM element. It allows the code to be generalized, and tied specifically to the affected element.
Doug Neiner
@Doug - Thanks for the + . You bring up a good point. It could be considered overkill if there's only one element with the behavior. Yours would be more efficient in that case.
patrick dw
@patrick, efficient yes... but then if you added an element down the line, mine would have to be rewritten. So it all really depends on the project.
Doug Neiner
my images already have a class :(
andrei
@andrei - Your images can have several classes. Using `addClass()` and `toggleClass()` simply appends an additional class to the image. The class doesn't need to add any style. It is just used as a flag.
patrick dw
+1  A: 

You just need to track whether it has been clicked or not. You can do it a few ways, but since you only have one element you are tracking, a variable is the simplest way to do it. I also optimized your code to utilize chaining. I also changed your selector to be more efficient. #slide is better than img#slide since an id is supposed to be unique:

$(document).ready(function(){
  var clicked = false;

  $('#slide')
    .animate({"opacity" : 0.7})
    .hover(function(){
      if(!clicked) {
        $(this).stop().animate({"opacity" : 1});
      }
    }, function(){
      if(!clicked){
        $(this).stop().animate({"opacity" : 0.7});
      }
    })
    .click(function(){
        clicked = true;
    });
});
Doug Neiner
+1 Using a local variable will be more efficient than my answer if there is ultimately only one element to deal with.
patrick dw
A: 

All the answers in this thread are good, and would work. But for the sake of it here's a different approach.

Based on your code and your question, what you're actually doing is removing the hover behaviour from the element. Which should be done as below:

$(document).ready(function(){

  $('img#slide').animate({"opacity" : .7});

  $('img#slide').hover(function(){
      $(this).stop().animate({"opacity" : 1});
  }, function(){
      $(this).stop().animate({"opacity" : .7});
  }); 

  $('img#slide').click(function(){
    $(this).unbind('hover');
  });
});

Which can be refactored to allow toggling of the behaviour in a novel way:

 $(document).ready(function(){

  var over = function(){
   $('img#slide').stop().animate({"opacity" : 1});
  };

  var out = function(){
   $('img#slide').stop().animate({"opacity" : 0.7});
  };

  var on = function(){
   $('img#slide').hover(over, out).one('click', off);
  }

  var off = function(){
   $('img#slide').unbind('hover').one('click', on);
  };

  $("img#slide").one('click', on);

  out.call();

 });

Note: I haven't tested this (I'm at work), but you get the idea.

Alex