Combining AddClass and RemoveClass Functions in Mootools Event Handlers

I am currently in the process of creating a CSS animation, and one aspect involves changing the class name of the body at specific intervals.

Since I am relatively new to Mootools (and JavaScript in general), my approach has been to add/remove classes to the body with delays, as shown below:

(function() {$(document.body).addClass('load');}).delay(20);
(function() {$(document.body).addClass('load-two');}).delay(2000);
(function() {$(document.body).addClass('load-three');}).delay(2700);
(function() {$(document.body).addClass('load-four');}).delay(4500);

However, as I delve deeper into the topic, I have started to believe that this may not be the most efficient way to achieve my goal.

The code above functions correctly in all the browsers I have tested, but I wonder if using a chain class would be a better approach. I have reviewed the Mootools documentation on setting up a chain, but I am having trouble getting the demo to work.

In essence, my question is whether there is a more effective way to write the code mentioned above and what advantages exist in using an alternative method?

Thank you.

Answer №1

Implementing a chain in mootools is relatively simple, but incorporating the Chain class as a mixin can be more complex.

Usually, the focus is on chaining Fx-based classes and methods rather than synchronous ones. For instance, if you have a tween effect with link: chain activated, you can use .chain(function() {}) to execute another action afterwards.

The callChain example works fine independently but lacks timing control options.

Another approach involves a linear timeline. In this scenario, each callback is executed at a specific time interval after the previous one. If you link actions together so that each step triggers the next one, you must consider the waiting time between actions carefully.

An alternative method is to defer the actions from the beginning.

Here's an attempt to streamline the process: http://jsfiddle.net/dimitar/mpzzq/

(function(){
    Chain.implement({
        slowChain: function(duration){
            // console.log(duration);
            this.callChain.delay(duration === null ? 500 : duration, this);
        }
    });

    var db = $(document.body);
    var fixBody = function(cn, delay) {
        console.log(arguments);
        db.addClass(cn);
        console.log(cn, delay);
        if (this.$chain.length) {
            this.slowChain(delay || 0);
        }
    };

    var myChain = new Chain(),
        funcs = [{
            fn: fixBody,
            args: ["load"],
            delay: 1980
        }, {
            fn: fixBody,
            args: ["load-two"],
            delay: 700
        }, {
            fn: fixBody,
            args: ["load-three"],
            delay: 2000
        }, {
            fn: fixBody,
            args: ["load-four"],
            delay: 0
        }];

    myChain.chain(
        funcs.map(function(el) {
            el.args.push(el.delay);
            return el.fn.bind.apply(el.fn, [myChain].concat(el.args));
        })
    );

    document.getElement("button").addEvents({
        click: function() {
            myChain.slowChain(20);
        }
    });
})();

In the array of objects within 'funcs', I define the function callback, arguments to pass, and the delay. Note that the function itself has the scope set to the chain instance and calls the next one in the chain. However, this can be modified as needed.

I hope this gives you some ideas.

Here's a second version using a decorator function to incorporate delays when calling the chain:

// Function decorator.
Function.implement({
    chainDelay: function(delay, bind) {
        // Allows setting a delay for chained functions and automatically calling the stack (if bind is a chain instance)
        var self = this,                 
            args = (arguments.length > 2) ? Array.slice(arguments, 2) : null;
        return function() {
            setTimeout(function() {
                self.apply(bind, args.concat(Array.from(arguments)));
                if (bind && bind.$chain && bind.$chain.length)
                    bind.callChain.call(bind);
            }, delay);
        }
    },
    justChain: function(bind) {
        // Executes a chained function when due and auto-calls the stack for the next one (if bind is a chain instance and available)
        var self = this, args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
        return function() {
            self.call(bind, args);
            if (bind && bind.$chain && bind.$chain.length)
                bind.callChain.call(bind);
        }
    }
});


var moo = new Chain();

moo.chain(
    // Some delayed functions.
    (function(what) {
        console.log(what);
    }).chainDelay(3000, moo, "hi"),
    (function(what, ever) {
        console.log(what, ever);
    }).chainDelay(3000, moo, "there", "coda"),
    (function(what) {
        new Element("div[id=foo][html=" + what +"]").inject(document.body);
    }).chainDelay(1000, moo, "mootools FTW!"),
    // Regular functions included here as well.
    (function() {
        document.id("foo").setStyle("color", "red")
    }).justChain(moo),
    (function() {
        document.id("foo").setStyle("background-color", "blue")
    })    
);

moo.callChain();

Example link: http://jsfiddle.net/dimitar/Y4KCB/4/

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

Learn the steps to Toggle Javascript on window resize

Is there a way to toggle Javascript on and off when the window is resized? Currently, resizing the window causes the navigation bar to stick and remain visible above the content. <script> if ( $(window).width() <= 1200 ) { }else{ $('nav& ...

Implement Material-UI Higher Order Components in a Class-based Component

I'm in the process of incorporating material UI into my class component rather than converting everything to Hooks. I'm unsure which approach would be simpler, utilizing Hooks or adapting what I currently have. https://material-ui.com/styles/bas ...

What is the best way to retrieve the value of a selected radio button with YUI?

Here is the structure of my radio buttons... <div id="test"> <input name="test1" value="a" type="radio"> <input name="test1" value="b" type="radio"> <input name="test1" value="c" type="radio"> </div> What is the best w ...

Is it possible for a Jquery radio button to trigger an infinite loop?

When I click on a radio button, I want to receive an answer from the PHP file. However, when I use the radio button, the alert appears in an endless loop. Why does this happen and how can I make the alert display only once? I tried with just a regular but ...

Is there a particular motive behind the decision for `arguments` to be treated as an object

Today while coding, I came across something puzzling. arguments.concat(someNumber); This line gave me an error for undefined function. Initially, I assumed that arguments was a native object for optimization purposes, but later discovered it's simp ...

Disable the border and background colors in CloudFlare Turnstile

I have implemented the CloudFlare reCaptcha Turnstile and I am looking to modify the widget by removing the border and background color. I believe this customization can be achieved using CSS or Javascript. Thank you for any assistance! ...

Performance challenges with an AngularJS application that uses pagination

Resolving Performance Issues in Paginated AngularJS Posts Application I developed a compact application that showcases JSON data as cards using AngularJS and Twitter Bootstrap 4. The app includes pagination with approximately 100 posts per page. var ro ...

Transfer the "file" from the busboy to the GM for FTP uploading

I'm looking to resize an uploaded image using nodejs and send it via ftp. I'll be utilizing nodejs, busboy, GraphicsMagick, and jsftp. var uploadFile = function(dir, req, cb) { req.busboy.on('file', function(fieldname, file, filename, ...

How can I pass standard HTML as a component in React?

I need help creating a Higher Order Component (HOC) that accepts a wrapper component, but allows me to pass standard HTML elements as inner content. Here is an example of what I want to achieve: type TextLike = string | {type,content} const TextLikeRender ...

I would love to hear your suggestions for a custom select element plugin in jQuery

After browsing multiple options online, I decided to turn to the expertise of the Stack Overflow community to ask for recommendations based on personal experience. I am specifically in search of a plugin that can substitute a select element with a custo ...

passport.js and express: TypeError - Router.use() must be given a middleware function, but instead received a ' + gettype(fn)

I encountered an error while using passport.js with Express.js TypeError('Router.use() requires a middleware function but got a ' + gettype(fn)) This issue arose from the following code: passport/local.js var LocalStrategy = require("passport ...

Animate out Material UI element with zoom effect and then remove it from the

I'm currently working on a dynamic user interface that allows for adding and removing items dynamically. Each item has both an add and remove button, with a special animation effect using Zoom. While this works smoothly when adding new items, I encoun ...

Validation of Selenium in the Node.js Environment

I have a block of code that is meant to verify if an element exists on the page and display a message accordingly. However, I am struggling to correctly check my elements. Should I use an object or an array for this task? And how can I check multiple value ...

JavaScript Arrays are not functioning properly within the Poo constructor

Attempting to insert data into a JavaScript Array within my constructor has resulted in this error message: TypeError: this.listeetudiant is undefined This is my constructor: function Cours(){ */the array causing trouble: */ this.listeetudiant=[]; */ ...

Exploring outside iframe data

My webpage includes an iframe A with a src attribute that links to a URL containing another embedded iframe B. I'm trying to figure out if it's possible to access the src of this nested iframe B. However, it appears that browser security measures ...

Transforming text colors dynamically using Vue.js

Here is an Angular code snippet: <div [style.color]="'#' + prod.id.substring(0,6)"> <small>{{ prod.id }}</small> </div> Now I want to create a similar code using vue.js. ...

Ways to successfully pass multiple parameters in Nuxt

Within Nuxt.js, when working with the code in pages/posts/_id.vue, it looks like this: <template> ...

Different body background color changes every second

I have a function called makeRandColor that generates a random color using RGB and template string literals. However, I am struggling to figure out how to make it work every second. I tried using setInterval but it doesn't seem to be functioning prope ...

Rendering Local HTML with local styling and scripts in React Native Webview

I am having trouble loading a local HTML, CSS, and JS file in my React Native webview. The CSS is not being applied to the HTML. Here is my folder structure: My HTML file, along with CSS, images, and JS file are all placed in the following app folder stru ...

Tips for accessing nested JSON values using Selenium

Here is a JSON snippet to work with: "ACCOUNT": { "AmountDue": "$36,812.99", "OutstandingBalance": "$27,142.27", "StatementTotal": "$9,670.72", "StatementDate": "12/6/2018", "DueByDate": "12/23/2018", ...