4

The HTML:

<a href="#" class="change">Old Text</a>
<a href="#" class="change">Old Text</a>

I want to change the "Text" with jQuery, delay two seconds and set it back to the original. I've tried timeout and delay unsuccessfully. The page has multipe items that have the same text "Add to cart", and switch to "Added", then back again.

The jQuery:

$('.change').html('first').delay(2000).html('second')

This fails. It ignores the first, and skips right to the second

_x = $(this);
$(_x).html('New Text');
_t = setTimeout(function(){
    $(_x).html('Old Text');
},2000);

This works, if the user clicks and doesn't trigger another before the 2 second reset. If someone clicks #1 and then clicks #2 before #1 has the text reset, it works on #2 but the text on #1 stays with the New Text.

I thought that since it's inside a function, that the timeout would be instantiated for each object with it's own instance of _t, but apparently not.

I'm not sure if it matters, but the elements are sometimes loaded dynamically, and the click binding is set accordingly

$(element).on('click','.change',function(_e) { ...

How can I handle this? Thank you in advance.

Mark
  • 229
  • 3
  • 9
  • 1
    Try using [jquery - $.each](http://api.jquery.com/each/) which will loop through all elements. Also if you can create a jsfiddle it will be convenient to debug. – Pazza22 Mar 14 '15 at 21:31

4 Answers4

6

UPDATE [March 04, 2017]

In response to Wim Mertens comment:

Unfortunately this doesn't work when you double click ...

You could tweak the code to handle both click and dblclick events and return the same expected behavior.

Based on this answer you could do:

var
  DELAY = 700,
  clicks = 0,
  timer = null,
  restoreText = function(target, oldText, newText) {
    target.html(newText); // set new text
    setTimeout(function() {
      target.html(oldText); // restore old text after n seconds
    }, 2000);
  }

$(".change").on("click", function(e) {
  clicks++; //count clicks
  var that = $(this); // $(".change")
  if (clicks === 1) {
    timer = setTimeout(function() {
      // set new text and restore old one after n seconds
      // parameters : target, oldText, newText 
      restoreText(that, that.html(), "new text")
      clicks = 0; //after action performed, reset counter
    }, DELAY);
    return false
  }
  // double click otherwise
  clearTimeout(timer); //prevent single-click action
  // set new text and restore old one after n seconds
  // parameters : target, oldText, newText 
  restoreText(that, that.html(), "new text")
  clicks = 0; //after action performed, reset counter
}).on("dblclick", function(e) {
  e.preventDefault(); //cancel system double-click event
});

See updated JSFIDDLE


[Original answer]

Try

// add a refresh button to image previews
$(".change").on("click", function () {
    var oldText = $(this).html();
    var that = $(this)
    $(this).html("new text");
    setTimeout(function () {
        that.html(oldText);
    }, 2000);
});

See JSFIDDLE

NOTE: if the elements to click are dynamically created, then try .on() in its delegated form like :

$(".parentSelector").on("click", ".change", function () {
    // handler
});
Community
  • 1
  • 1
JFK
  • 40,963
  • 31
  • 133
  • 306
  • This was the right answer, but not for the right reason - but it still finally clued me in to what was wrong. The redeclaring the variables fixes it. See the following example, same exact code for both examples, with the exception of the 'var' https://jsfiddle.net/5n9k47be/1/ – Mark Mar 14 '15 at 22:33
  • 1
    @Mark : you have to declare the variables somewhere in your document. If you add `"use strict";` at the top of your jsfiddle, you will see that the first piece of code triggers the js error `ReferenceError: assignment to undeclared variable oldText` ... just because you omitted the `var` declaration. The second piece of code works as it should. – JFK Mar 14 '15 at 23:55
  • 1
    @JFK I was looking for a solution like this. Unfortunately this doesn't work when you double click (some people do that apparently :), the new text doesn't revert back to the old. Any idea how to fix this? Thanks! – Wim Mertens Mar 02 '17 at 23:06
  • 2
    @JFK I was tinkering with this a bit more. If you click more than twice it still doesn't work (I guess for really impatient people :) so I thought to simplify it by adding and removing a class that sets pointer-events to none. Created a fiddle here: https://jsfiddle.net/c253gmom/ – Wim Mertens Mar 05 '17 at 20:13
1

If I were doing this I'd do this:

HTML:

<div class="change">Add to cart</div>
<div class="change">Add to cart</div>

jQuery:

var wait;
$(document).ready(function(){ 

    $( ".change" ).click(function() {
        clearTimeout(wait);

        $(this).html("Added!");
        // Add item to cart

        wait = setTimeout(function(){ 
            $(".change").html("Add to cart");
        }, 2000);
    });
});

Of course I've used div tags instead of hyperlinks. Demo here!

CodeUK
  • 421
  • 1
  • 5
  • 13
0

In your Second code, dont double-wrap:

_x = $(this);
_x.html('New Text');
_t = setTimeout(function(){
    _x.html('Old Text');
},2000);

in your first, if its called inside the click event callback Function, Start with $(this).html(.....

Andi
  • 113
  • 3
0

Try

var newtext = "New Text";
$(document).on("click", ".change", function() {
$(this).map(function(i, el) {
  $(el).html(function(idx, html) {
     $(this).delay(2000, "html").queue("html", function() {
       $(this).html(html)
     });
     return html.replace(html, newtext)
  }).dequeue("html")
})
});
$("body").append("<a href=# class=change>Old Text</a>"
                + "\n<a href=# class=change>Old Text</a>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
guest271314
  • 1
  • 15
  • 104
  • 177