Search code examples
javascriptjqueryhtmlcssinnerhtml

jQuery: Delayed replacing of a div's innerHTML?


I'm trying to use jQuery to fade out an element, replace its innerHTML and fade it back in after the content has been replaced. Replacing the content of the element using the .html()-method along with the .find()-method works, but as soon as I am trying to add a delay to the function that is finding and placing the innerHTML, it stops working. This is my code so far:

'#current-title' is the element of which the content is supposed to be replaced; '#title1' contains the text which is supposed to end up in '#current-title'. All of this should happen with a transitioned opacity change of '#current-title' before and after the new text has been placed.

$(document).ready(function() {
  $.replace = function() {

  $('#current-title').css("opacity", "0");

  setTimeout(function() {
    $('#current-title').html($(this).find('#title1').html());
  }, 500);

  setTimeout(function() {
    $('#current-title').css("opacity", "1");
  }, 1000);

  alert('Title has been replaced.');
  };

  $(".replace-btn").click(function() {
    $.replace();
  });
});

A reduced version of the same function, only replacing the html of '#current-title' without a setTimeout, works just fine:

$(document).ready(function() {
  $.replace = function() {

    $('#current-title').html($(this).find('#title1').html());

    alert('Title has been replaced.');
  };

  $(".replace-btn").click(function() {
    $.replace();
  });
});

Why is the setTimeout in my first piece of code not working?


$(document).ready(function() {
  $.replaceDelayed = function() {

    $('#current-title').css("opacity", "0");

    setTimeout(function() {
      $('#current-title').html($(this).find('#title1').html());
    }, 500);

    setTimeout(function() {
      $('#current-title').css("opacity", "1");
    }, 1000);

    setTimeout(function() {
      alert('Title has been replaced.');
    }, 1000);
  };

  $(".replace-btn").click(function() {
    $.replaceDelayed();
  });
});


$(document).ready(function() {
  $.replaceNormal = function() {

    $('#current-title').html($(this).find('#title1').html());

    alert('Title has been replaced.');
  };

  $(".replace-btn2").click(function() {
    $.replaceNormal();
  });
});
.title {
  visibility: hidden;
}

* {
  transition: opacity 0.3s ease;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="current-title">
  <a>Project Title #0</a>
</div>

<br>

<div class="title" id="title1">
  <a>Project Title #1</a>
</div>

<br>

<button class="replace-btn">
  Replace Title (with delay)
</button>

<button class="replace-btn2">
  Replace Title (without delay)
</button>


Solution

  • In your code, without setTimeout, this refers to the window object. window.find will search for a string in the current window. It will not search for the element in the document. Refer this

    this inside the setTimeout` method returns a function object.

    So your code works after removing this.

    This works.

    $(document).ready(function() {
      $.replaceDelayed = function() {
    
        $('#current-title').css("opacity", "0");
    
        setTimeout(function() {
          //console.log(this) returns the window object
          $('#current-title').html($('#title1').html());
        }, 500);
    
        setTimeout(function() {
          $('#current-title').css("opacity", "1");
        }, 1000);
    
    
      };
    
      $(".replace-btn").click(function() {
        $.replaceDelayed();
      });
    });
    
    
    $(document).ready(function() {
      $.replaceNormal = function() {
        //console.log(this); returns a function object
        $('#current-title').html($('#title1').html());
    
        alert('Title has been replaced.');
      };
    
      $(".replace-btn2").click(function() {
        $.replaceNormal();
      });
    });
    .title {
      visibility: hidden;
    }
    
    * {
      transition: opacity 0.3s ease;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="current-title">
      <a>Project Title #0</a>
    </div>
    
    <br>
    
    <div class="title" id="title1">
      <a>Project Title #1</a>
    </div>
    
    <br>
    
    <button class="replace-btn">
      Replace Title (with delay)
    </button>
    
    <button class="replace-btn2">
      Replace Title (without delay)
    </button>