jQuery - Comparing Nested and Unnested Transition and Animation Event Handlers/Listeners

At the moment, I am working on a block of code that triggers every time a specific ajax call is made.

The snippet I'm using looks like this (although it might throw an error due to absence of html or css - but that's not my concern as I just want to showcase my code):

$(document).ajaxStart(function() {
  if ($('.spinner').length < 1) { //checking for existing spinner
    $('body').prepend('<div class="spinner" title="Spinner stuck? Click to remove!"></div>');
  }
  $('body div').not('.spinner').css('opacity', '0.5'); 
});

.done(function(xhr) {
  $('body div').not('.spinner').css('opacity', '0');
  $('body').one('transitionend', function(e) {
    $('body div').not('.spinner').remove();
    $('body').append(xhr);
    $('body div').not('.spinner').css('opacity', '0.1');
    $('body').one('transitionend', function(e) {
      $('body div').css('opacity', '1';
      $('.spinner').remove();
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

This setup features nested .one('transitionend')s which I'm analysing to determine its correctness. This piece of code handles login and logout responses from ajax calls. While it works well for logging in most cases, it seems to be failing for logout due to issues with registering the end transition. Consequently, the process freezes at

$('body div').not('.spinner').css('opacity', '0.1');
.

I've created a quick test on this jsfiddle to compare nested versus unnested event handlers.

The two approaches seem to yield similar results. However, early on, there were freezing issues when clicking too frequently on either - this was addressed by adding the log bit -

$('#log span').text($('#div1').text());
, etc.

Here's a snippet of the updated jsfiddle:

//code snippet here...
//more code snippets here...

In light of these experiments, I aim to identify the superior method. Which option offers smoother execution and fewer problems for the code or browser? Is there a more effective way to manage code reliant on transitions or animations?

My attempts at utilizing jQuery's .queue and .delay have not yielded results in this context. Perhaps another approach could prove fruitful? Although setTimeout() remains a possibility, maintaining synchronicity may require nesting elements below it. Moreover, while .one('transitionend') appears functional in most instances irrespective of nesting, some scenarios demand further investigation.

UPDATE:

In response to feedback provided on my code:

Some minor pointers on your code, don't do css in Jquery but append/prepend classes with the opacity value. Use variables instead of going through the DOM with every selector. – Jan_dh

I have revised the corresponding jsfiddle to adjust classes rather than directly modifying CSS properties. You can access the updated version through this link: here. However, I seek clarification on:

Use variables instead of going through the DOM with every selector.

If this notion aligns with addressing my query, I welcome insights from individuals who comprehend Jan_dh's suggestion.

Answer №1

To implement a smooth transition between elements, you can utilize various jQuery methods such as .queue(), $.map(), and .one("transitionend"). By attaching the transitionend event to the current transitioning element and setting the handler to call the next function in the queue when the transition is completed, you can control the flow of transitions effectively. Additionally, you can handle multiple columns of elements by using .slice() to split them into separate arrays based on specific criteria like the element ID starting with "div". Pass these arrays to event handlers using event.data and filter specific columns with $.grep() or .filter(). Manipulate the collection of elements by setting their data attributes to control the default action during transitions triggered by user interaction.

var newCss = {
  backgroundColor: "blue",
  width: "25%",
  color: "white"
}
// define `log` variable as `"#log span"`
, log = $("#log span")
// define `divs` variable for elements with IDs starting with "div"
, divs = $("[id^=div]")
// define `col1` as elements from index 0 through 7
, col1 = divs.slice(0, 7)
// define `col2` as elements from index 7 till the end
, col2 = divs.slice(7, divs.length);

function queueColumn(col, name) {
  // set each element in the collection as active
  return col.data("active", true).queue(name, $.map(col, function(div) {
    return function(next) {
      log.text($(div).one("transitionend", next).css(newCss).text())
    }).dequeue(name).promise(name)
}

function handleQueue(e) {
  var curr = $.grep(e.data, function(col) {
    return col.filter(e.target).length
  }).pop();
  var name = `col${$.inArray(curr, e.data) + 1}-${$.now()}`;
  
  if (curr.data("active") === undefined) {
    curr.data("active", false);
  }
  
  if (curr.data("name") === undefined) {
    curr.data("name", name);
  }
  
  var inprogress = curr.data("active");
  
  return !inprogress ? queueColumn(curr, name).then(function() {
    this.removeAttr("style").data({"active": false, "name": void 0});        
  }) : inprogress
}

$("#div1, #div8").click([col1, col2], handleQueue);
body {
  display: flex;
  align-items: flex-start;
}
div {
  display: inline-block;
  width: 25%;
}
div > div {
  border: 4px dotted red;
  transition: .25s;
  display: block;
  width: 10%;
  padding: 4px 8px;
  margin: 16px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
<div>
  <div id="div1">1</div>
  <div id="div2">2</div>
  <div id="div3">3</div>
  <div id="div4">4</div>
  <div id="div5">5</div>
  <div id="div6">6</div>
  <div id="div7">7</div>
</div>
<div id="log">We got to: <span></span>
</div>
<div>
  <div id="div8">8</div>
  <div id="div9">9</div>
  <div id="div10">10</div>
  <div id="div11">11</div>
  <div id="div12">12</div>
  <div id="div13">13</div>
  <div id="div14">14</div>
</div>

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

Generate a query string by selecting certain input values using a button, while disregarding the rest

Currently working on a project involving a large calculator designed as a form, which contains 150 inputs. My goal is to generate a query string using only 17 of these inputs for the user to share. I am utilizing PHP to populate the inputs from the URL s ...

In the following command, where is the PORT stored: ~PORT=8080 npm App.js?

section: Let's consider the following code snippet located in the App.js file: console.log(`This is the port ${process.env.PORT}`); Is there a method to retrieve the value of PORT from outside the running process? ...

Creating a cross-platform file writer with PHP and JavaScript

My current challenge involves using buttons on an HTML page to trigger a PHP program that writes to a text file. Despite receiving a success message from my Ajax function, the file that should have been written to doesn't exist. Here's a snippet ...

Why is my <li> not centered and my navbar appears 'transparent' when I scroll through in HTML CSS?

https://i.sstatic.net/Qa2iS.png I am looking to achieve a solid navbar with centralized workouts and diets. https://i.sstatic.net/4bUlX.png I attempted to create a navbar, but when I added a search bar, it caused my "Workouts" and "Diets" to be off-center ...

Implementing the Jssor slider

Recently, I've been using the jssor slider on multiple pages without any issues. However, I am now facing some challenges. Ideally, I want the slider to be hidden initially and then displayed with another script. While I have managed to achieve this v ...

Modify styling of complete list upon clicking in React

For my latest project, I developed a basic todo application using React. One of the key features is that when a user clicks on a checkbox, the corresponding todo item's CSS changes to show a strike-through effect. Additionally, a button appears on hov ...

Developing typeScript code that can be easily translated and optimized for various web browsers

Can TypeScript alleviate the worry of having to use code such as this (especially when considering browsers like IE that may not support indexOf)? arrValues.indexOf('Sam') > -1 Does the transpiling process in TypeScript generate JavaScript c ...

Ways to Ensure the Footer Stays Beneath Your Image Gallery

After successfully keeping the footer at the bottom of other pages on my website, I'm facing a challenge with my photo gallery page. The footer stubbornly sits in the middle of the page. :( This is the HTML code for that particular page: html { ...

What are the reasons behind the ineffectiveness of !important in CSS?

I am looking to increase the font-size of all text on my website to 200%, you can find some test code in this Fiddle link. If it is a PX issue, why does the code work when I add the style to "<h2>"? <div> <h2 class="test" style="font-size: ...

Container that can be scrolled under varying heights

Trying to structure some CSS in order to create a website that resembles the layout of a typical desktop application: Almost there, but struggling to make the scrollable panel stick to the bottom of the viewport and show a scrollbar instead of overflowing ...

What is the best way to rotate a group in ThreeJS while keeping its center as the pivot

I am currently attempting to construct a functioning Rubik's Cube using ThreeJS. However, I have encountered an issue with rotating the sides. To build the Rubik's Cube, I am adding individual smaller cubes in this manner: const rubiksCube = new ...

react componentdidupdate triggers never-ending iteration

When I trigger an API call to elasticsearch using onChange, it prompts a list for autocomplete. To make sure that my store is updated before rerendering, I included componentDidMount so that I am not lagging behind by one tick. Here is the code snippet: c ...

The CSS transition seems to be malfunctioning

I need help figuring out how to make the submenu in the navigation bar appear with a transition effect. The CSS code I'm currently using is: #navigation li ul { display: none; width: auto; position: absolute; margin: 0; padding: 0; ...

Simple HTML/CSS text blocks positioned beside images in a list format

I'm attempting to design a list (ul) where each li has an img on the left and text aligned to the left (including a title and paragraphs) positioned next to the image on the right. I've experimented with float: left and various display propertie ...

Looking for Protractor CSS functionalities nodes

I tried the code below but am having trouble locating the "Login" text using Protractor: <div _ngcontent-c2="" class="align-center"> <img _ngcontent-c2="" alt="Autoprax" class="ap-logo" src="/images/apLogoSmall.svg" style="width: 100%"> ...

The SDK generated by AWS API Gateway does not include the JavaScript client file

After setting up my API with the AWS Api Gateway Service, I am now looking to integrate the javascript SDK into a basic webpage. The provided instructions for using the javascript SDK can be found here. However, they mention importing a js file named apig ...

"Troubleshooting problems with jQuery accordion collapse and styling using CSS

I'm currently dealing with an issue regarding my accordion design. I have customized the stylesheet using themeroller, but when I collapse one of the sections, the header changes to black instead of reverting back to its original red color. I've ...

Tips for creating a React component input field design

I am currently using React version 18.2.0 and I am looking to create an input field similar to the image below. The goal is to allow users to add multiple chips, save them, and then pass them to the backend project. https://i.sstatic.net/PzF7v.png I have c ...

Two approaches for one single object

I'm trying to figure out why this particular code works // ....................................................... var character = { name: 'Joni', type: 'blond', sayName: function() { return this.name; }, sayT ...

Monitoring and refining console.error and console.log output in CloudWatch

I've encountered a situation where my lambda function includes both console.error and console.log statements, which Node.js interprets as stderr and stdout outputs respectively. However, upon viewing the logs in CloudWatch, I noticed that they appear ...