views:

1867

answers:

4

Context: On my product website I have a link for a Java webstart application (in several locations).

My goal: prevent users from double-clicking, i. e. only "fire" on first click, wait 3 secs before enabling the link again. On clicking, change the link image to something that signifies that the application is launching.

My solution works, except the image doesn't update reliably after clicking. The commented out debug output gives me the right content and the mouseover callbacks work correctly, too.

See it running here: http://www.auctober.de/beta/ (click the Button "jetzt starten").

BTW: if anybody has a better way of calling a function with a delay than that dummy-animate, let me know.

JavaScript:

<script type="text/javascript">
      <!--
        allowClick = true;
        linkElements = "a[href='http://www.auctober.de/beta/?startjnlp=true&amp;rand=1249026819']";
        $(document).ready(function() {
            $('#jnlpLink').mouseover(function() {
                if ( allowClick ) {
                    setImage('images/jetzt_starten2.gif');
                }
            });
            $('#jnlpLink').mouseout(function() {
                if ( allowClick ) {
                    setImage('images/jetzt_starten.gif');
                }
            });

           $(linkElements).click(function(evt) {
                if ( ! allowClick ) {
                    evt.preventDefault();
                }
                else {
                    setAllowClick(false);
                    var altContent = $('#jnlpLink').attr('altContent');
                    var oldContent = $('#launchImg').attr('src');
                    setImage(altContent);
                    $(this).animate({opacity: 1.0}, 3000, "", function() {
                        setAllowClick(true);
                        setImage(oldContent);
                    });
                }
            });

        });

        function setAllowClick(flag) {
            allowClick = flag;
        }
        function setImage(imgSrc) {
            //$('#debug').html("img:"+imgSrc);
            $('#launchImg').attr('src', imgSrc);
        }
      //-->
</script>
A: 

Check out the BlockUI plug-in. Sounds like it could be what you're looking for.

You'll find a nice demo here.

Riri
Ah, no, sorry, I don't want to block the whole UI, just the link.
jmagica
OK. I see. You could also use it to just block an element but it might not be what you're looking for either. http://malsup.com/jquery/block/#element
Riri
A: 

A delay can be achieved with the setTimeout function

setTimeout(function() { alert('something')}, 3000);//3 secs

And for your src problem, try:

$('#launchImg')[0].src = imgSrc;
I.devries
$('#launchImg')[0].src is a strange hybrid to use. If you're getting an element by ID in jQuery, you'll get one element back. The example in the original question that uses $("#launching").attr("src", "..."); is correct.
Sohnee
But as with other attributes, it doesn't always work correctly.(Try doing element.setAttribute('class', 'someClass')) in IE. Same with colspan.altering the .src attribute does not produce the same behavior in javascript as setAttribute('src', '...');jQuery always returns an array, if you want the element, not the jQuery object, you need to use [0];
I.devries
Although I agree with Sohnee that it's strange, I'm upvoting to get rid of the downvote because, indeed, it's worth _trying_.
Domenic
There's nothing wrong with `$('#launchImg')[0]`. Sometimes you want to get at the real DOM object and this beats a function call.
Justin Johnson
A: 

Add this variable at the top of your script:

var timer;

Implement this function:

function setFlagAndImage(flag) {
    setAllowClick(flag);
    setImage();
}

And then replace the dummy animation with:

timer = window.setTimeout(function() { setFlagAndImage(true); }, 3000);

If something else then happens and you want to stop the timer, you can just call:

window.clearTimeout(timer);
Sohnee
Don't pass a string to window.setTimeout as it calls eval() and slows things down.
I.devries
Actually, with JavaScript being an interpreted language, you won't see a performance reduction in the scenario detailed above. eval is perfectly fine for this kind of use.
Sohnee
Eval is completely unnecessary for this. `setTimeout(function() { setFlagAndImage(true); }, 3000);` is preferred.
Justin Johnson
A: 

...or just use:

$(this).animate({opacity: '1'}, 1000);

wherever you want in your code, where $(this) is something that is already at opacity=1...which means everything seemingly pauses for one second. I use this all the time.

Emlyn