What is the process for resetting a JQueryUI effect animation?

I'm facing an issue with two timer bars that each wind down over a 5-second period. When I try to stop and reset the first timer, it simply continues from where it left off instead of resetting.

The desired behavior is as follows:

  • Timer1 starts
  • User hits key
  • Timer1 stops halfway complete
  • Timer2 starts
  • Timer2 expires
  • Timer1 resets to 100% and starts again

This is how Timer1 is started:

function StartTimer1(){       
 $("#timer-bar").show().width("100%");
    
$("#timer-bar").hide({
            effect: "blind",
            easing: "linear",
            duration: 5000,
            direction: "left",
            complete: function () {
                //do stuff
            }
        });
}

When a key is hit, the following code is executed:

//Stop Timer1
     $("#timer-bar").stop(true, false);

//Start Timer2 
    $("#answer-timer-bar").hide({
        effect: "blind",
        easing: "linear",
        duration: 5000,
        direction: "left",
        complete: function () {
            //do stuff
        }
    });

After Timer2 expires, hitting another key triggers StartTimer1() again. Despite resetting the width to 100% before starting the animation, it simply continues from where it stopped initially. I've experimented with using queues and adding unique queue names to each timer option, but the timer fails to start when queues are specified. I've also tried different options for clearQueue and jumpToEnd parameters with Stop(), without achieving the desired behavior.

Any assistance on this matter would be highly appreciated. Thank you!

JSFiddle: https://jsfiddle.net/58rzg6w0/7

Answer №1

Advantages of Using Animation over Hide and Show Methods:
After conducting thorough research and referring to this insightful post on Stack Overflow, it is evident that utilizing $(selector).animate() provides greater control over animations compared to using $(selector).hide() and $(selector).show().

Implementation of Container Elements for Animation:
I have adopted a strategy where the CSS styles are segregated, and overlays are incorporated for the animation itself to avoid any collapse in the container (which may occur if the element is set to display: none). While this approach may vary in usefulness depending on your objective, separating the animation from the container can be advantageous without any drawbacks. Furthermore, you still retain the option to hide them as needed.

Addressing Timing Issues during Animation Resumption:
A potential concern arises when timers are paused and resumed amidst an ongoing animation sequence, leading to a situation where the animation continues at the same pace despite covering a smaller distance – resulting in a slower effect. However, by resetting the animation for 'timer1' as demonstrated in your example, this obstacle can be overcome successfully. Otherwise, adjustments to the animation duration relative to both the progress and total length become necessary, as exemplified in the script below.

Adding a Fun Element - Time Display:
Typically, a timer serves to display time intervals; hence, I have included the animation duration within the overlay for reference. This simple addition, accompanied by suitable styling, offers a supplementary feature that might enhance the overall user experience. The duration setting for the animation can be specified on the timer element via data-duration (in milliseconds).

$('document').ready(function() {
  ResetAll();
});

function TimeLeft(id, initialTime) {
  const $timer = $('#' + id);
  const $overlay = $timer.find('.overlay');
  const percentageToGo = (parseInt($overlay.css('width')) / parseInt($timer.css('width')));
  return percentageToGo * initialTime;
}

function StartTimer(id, onComplete = null) {
  const $timer = $('#' + id);
  const $overlay = $timer.find('.overlay');
  const duration = $timer.data('duration');
  const time = TimeLeft(id, duration);
  $overlay.animate({
    width: '0%'
  }, {
    duration: time,
    easing: 'linear',
    step: function() {
      $overlay.html(Math.round(TimeLeft(id, duration)) / 1000);
    },
    complete: function() {
      // $timer.css('display', 'none'); // remove all comments to hide the timer element completly
      $overlay.html('');
      if (onComplete && typeof onComplete === 'function') {
        onComplete();
      }
    }
  });
}

function StopTimer(id) {
  $('#' + id + ' .overlay').stop(true, false);
}

function ResetTimer(id) {
  const $timer = $('#' + id);
  const $overlay = $timer.find('.overlay');
  $overlay.stop(true).css('width', '100%');
  // $timer.css('display', 'block'); // remove all comments to hide the timer element completly
  $overlay.html(Math.round(TimeLeft(id, $timer.data('duration'))) / 1000);
}

function StopTimer1AndStartTimer2() {
  ResetTimer('timer1');
  ResetTimer('timer2');
  StartTimer('timer2', function() {
    // $('#timer2').css('display', 'none'); // remove all comments to hide the timer element completly
    StartTimer('timer1');
  });
}

function ResetAll() {
  ResetTimer('timer1');
  ResetTimer('timer2');
  // $('.timer').css('display', 'block'); // remove all comments to hide the timer element completly
}
.timer {
  position: relative;
  height: 30px;
  width: 100%;
  z-index: 1;
}

.overlay {
  color: white;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: -1;
}

#timer1 .overlay {
  background-color: red;
}

#timer2 .overlay {
  background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<div id="timer1" data-duration="5000" class="timer">
  <div class="overlay"></div>
</div>
<div id="timer2" data-duration="3000" class="timer">
  <div class="overlay"></div>
</div>
<p>This first button is probably what you want, the rest is extra:</p>
<button onclick="StopTimer1AndStartTimer2();">Stop Timer1 - Reset Timer1 - Start Timer2 - on complete Start Timer2</button>
<button onclick="StartTimer('timer1');">Start/Resume Timer1</button>
<button onclick="StartTimer('timer2');">Start/Resume Timer2</button>
<button onclick="StartTimer('timer1'); StartTimer('timer2');">Start/Resume All</button>
<button onclick="StopTimer('timer1');">Stop Timer1</button>
<button onclick="StopTimer('timer2');">Stop Timer2</button>
<button onclick="StopTimer('timer1'); StopTimer('timer2');">Stop All</button>
<button onclick="ResetTimer('timer1');">Reset Timer1</button>
<button onclick="ResetTimer('timer2');">Reset Timer2</button>
<button onclick="ResetAll();">Reset All</button>

Answer №2

If you need to restart the animation:

// Clear any existing styles
$("#timer-bar").removeAttr('style');
// Set initial width to 100%
$("#timer-bar").show().width("100%");

Alternatively, you can use:

$('#timer-bar').stop(true).css('width', '100%');

Answer №3

If you want to duplicate timer1 and reset it to its original value, you can use the .clone() function initially and replace it with the .replaceWith() method after timer2 effect is completed:

var initialValue = null;
function StartTimer1() {
    if (initialValue == null) {
        initialValue = $("#timer1").clone();
    } else {
        $("#timer1").replaceWith(initialValue);
    }
    $("#timer1").show().width("100%");

    $("#timer1").hide({
        effect: "blind",
        easing: "linear",
        duration: 5000,
        direction: "left",
        complete: function () {
        }
    });
}

function StopTimer1(){
    $("#timer1").stop(true, false);

    $("#timer2").hide({
        effect: "blind",
        easing: "linear",
        duration: 2000,
        direction: "left",
        complete: function () {
            StartTimer1();
        }
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div id="timer1" style="height:30px; width:100%; background-color:red"></div>
<div id="timer2" style="height:30px; width:100%; background-color:blue"></div>
Click First button, then click second, then click first again
<button onclick="StartTimer1();">Start Timer1</button><button onclick="StopTimer1();">Stop Timer1 and Start Timer2</button>

Answer №4

To eliminate the placeholder, use .stop(true, true) (

.stop( [clearQueue ] [, jumpToEnd ] )
). The jumpToEnd parameter will hide it temporarily, so you can show it again and call it back after the timer2 finishes:

 function StartTimer1() {
  $("#timer1").hide({
    effect: "blind",
    easing: "linear",
    duration: 5000,
    direction: "left",
    complete: function() {}
  });
}

function StopTimer1() {
  $("#timer1").stop(true, true).show();

  $("#timer2").hide({
    effect: "blind",
    easing: "linear",
    duration: 2000,
    direction: "left",
    complete: function() {
      StartTimer1()
    }
  });
}

Example demonstrating resetting the red bar immediately after a button press:

function StartTimer1() {
  $("#timer1").hide({
    effect: "blind",
    easing: "linear",
    duration: 5000,
    direction: "left",
    complete: function() {}
  });
}

function StopTimer1() {
  $("#timer1").stop(true, true).show();

  $("#timer2").hide({
    effect: "blind",
    easing: "linear",
    duration: 2000,
    direction: "left",
    complete: function() {
      StartTimer1()
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="timer1" style="height:30px; width:100%; background-color:red">

</div>


<div id="timer2" style="height:30px; width:100%; background-color:blue">

</div>

Click First button, then click second, then click first again
<button onclick="StartTimer1();">
Start Timer1
</button>


<button onclick="StopTimer1();">
Stop Timer1 and Start Timer2
</button>

If you wish to reset the red bar after the blue animation completes:

Use .stop(true, false); and reset the styling (.attr("style")) when the blue bar's animation finishes.

function StartTimer1() {
  $("#timer1").hide({
    effect: "blind",
    easing: "linear",
    duration: 5000,
    direction: "left",
    complete: function() {}
  });
}

function StopTimer1() {
  $("#timer1").stop(true, false);

  $("#timer2").hide({
    effect: "blind",
    easing: "linear",
    duration: 2000,
    direction: "left",
    complete: function() {
      $("#timer1").attr("style", "height:30px; width:100%; background-color:red");
      StartTimer1();
    }
  });
}

function StartTimer1() {
  $("#timer1").hide({
    effect: "blind",
    easing: "linear",
    duration: 5000,
    direction: "left",
    complete: function() {}
  });
}

function StopTimer1() {
  $("#timer1").stop(true, false);

  $("#timer2").hide({
    effect: "blind",
    easing: "linear",
    duration: 2000,
    direction: "left",
    complete: function() {
      $("#timer1").attr("style", "height:30px; width:100%; background-color:red");
      StartTimer1();
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="timer1" style="height:30px; width:100%; background-color:red">

</div>


<div id="timer2" style="height:30px; width:100%; background-color:blue">

</div>

Click First button, then click second, then click first again
<button onclick="StartTimer1();">
Start Timer1
</button>


<button onclick="StopTimer1();">
Stop Timer1 and Start Timer2
</button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Searching for documents in MongoDB using minimum as a condition in the query

My user base is expansive, each facing a unique set of problems at different times. I am currently searching for users or documents that share a specific problem type (referred to as "top":1) but only among those, I am interested in isolating the entry wit ...

Troubleshooting dropzone configuration issues and encountering the error message "Dropzone already attached"

I've been utilizing dropzone to manage image uploads on the front-end of my website. Initially, everything was running smoothly while using it as a CDN in the head section. However, I recently attempted to download and integrate it into assetic like t ...

"Enforce a specific height on a div that is exclusively showing a background

I have been trying to use a div element to showcase a specific color, where the background color acts as the content. However, no matter what height or width settings I input, I am unable to achieve the desired size for the div. Even after experimenting w ...

Attaching a function to the "onselect" event that manages the character limit within an input text field

I have been developing a function to restrict the number of characters a user can enter into a text field. Here's what I have so far: $.fn.restringLength = function (id, maxLen) { $(id).keypress(function(e){ var kCode = ...

How can I conceal text using css in specific situations without risking a penalty from search engines?

Currently, I'm developing an illustration tool that needs to be visually appealing to users, while also being accessible to screen readers and search engines. Below is the HTML code I'm working with: <span class="card">A new idea is presen ...

The setInterval() function is not functioning properly when used with PHP's file_get_contents

Currently, I'm encountering an issue while attempting to use the function get_file_contents() within a setInterval(). The objective is to continuously update some text that displays the contents of a file. Below is the code snippet: <script src="h ...

My CSS files are not being included by grunt-bower-install

As someone who is relatively new to bower and grunt, I'm struggling with some basic tasks. After running bower install --save bootstrap, my goal is to use grunt-bower-install to update my js & css files as per the instructions on their documentat ...

The footer has a wandering nature, constantly moving around as the wrapper mysteriously vanishes

I understand that this question has been asked multiple times before, but I am struggling to get it right! My goal is to keep the footer at the bottom of the page, but it seems to be acting strangely. Here is my HTML: <!DOCTYPE HTML> <html& ...

Develop a dynamic progress bar using jQuery

I am having trouble creating a percentage bar using jquery and css. The code I have written is not working as expected, particularly the use of jquery css({}). Here is the code snippet: *'width' : width - seems to be causing issues for me / ...

The useEffect hook is triggering multiple unnecessary calls

Imagine a tree-like structure that needs to be expanded to display all checked children. Check out this piece of code below: const { data } = useGetData(); // a custom react-query hook fetching data from an endpoint Now, there's a function that fin ...

Using AngularJS with the Phonegap Facebook plugin

I am looking to build a Javascript app and deploy it on Android and iOS using Phonegap. My goal is to integrate Facebook login into the app. After exploring the phonegap-facebook plugin, I was able to successfully implement the Facebook login feature. How ...

The mysterious plugin "transform-runtime" has been detected in the ".babelrc" file located in "UsersPhpstormProjectseasy-essay"

After downloading a GitHub repository, I came across a file named .babelrc.json with the following contents: { "presets": [ "es2015", "stage-0" ], "plugins": [ "transform-runtime", "add-module-exports", "transform-decorators-lega ...

What is the constant name returned by jQuery's .css method for font-weight?

I previously defined the font-weight of an element using this code snippet $('#myid').css('font-weight', 'bold'); However, when I attempt to check the value later on $('#myid').css('font-weight') I rece ...

Oops! Looks like there's a hiccup with the express-validator plugin as the validation fails due to req.checkBody not being recognized as

Currently, I am setting up a post route to handle a submit request. The code snippet provided is from my user.js route: var express = require('express'); var router = express.Router(); var multer = require('multer'); var upload = multe ...

What is the reason IE7 does not recognize these two strings as equal?

My event handler is designed to remove an element from a list if the corresponding checkbox is unchecked. When the checkbox is clicked, I first capture the value of the label associated with it: var label = $(this).next().html(); Next, I loop through the ...

Sending an object from Rails to Javascript

My MapsController is def show @outlet=OUtlet.all render 'maps/map' end In the view page map.html.erb, I iterate through each outlet to display their latitude and longitude: <% @outlet.each do |product| %> <%= product.latitu ...

Unable to properly structure data in JSON request

Trying to fill JSON request with data from phpsearch.php file (displayed below) <?php include "base.php"; $name = $_GET["name"]; $query = "SELECT lat, lng FROM markers WHERE name = '".$name."'"; $result = mysql_query($query); $json = array(); ...

Alignment of a Definition List with Omissions of Definitions

Often, I come across applications with forms containing optional fields. In the Show view, these fields tend to "collapse" together and lose alignment with their corresponding labels. For instance, if I have 3 fields that should be displayed as: Phone: 3 ...

Utilizing the jQuery .wrap() method to encase the surrounding HTML

I am currently using the following jQuery code: jQuery( ".quantity" ).wrap( "<div class=\"engrave_button\"></div>" ) to wrap the quantity div with the engrave_button div. However, I need to include the ...

Tips for resizing mesh along the global axis

Have you ever used an online 3D editor that allows you to manipulate individual meshes by moving, scaling, and rotating them? This editor utilizes custom transform controls inspired by the TransformControls code from three.js. Here is a snippet of code fro ...