Issue with my lazyloading extension for Mootools

Seeking to create a plugin for sequential image downloads using MooTools. Assuming there are images with the img tag inside a div with the class imageswrapper. The goal is to download each image in order, one after the other until all images are loaded.

window.addEvent('domready', function(){
// retrieve all images within the div with the class 'imageswrapper'
var imagesArray = $$('.imageswrapper img');
var tempProperty = '';
// hide the images and assign the 'data-src' attribute to prevent background downloading
for (var i=0; i<imagesArray.length; i++) {
    tempProperty = imagesArray[i].getProperty('src');
    imagesArray[i].removeProperty('src');
    imagesArray[i].setProperty('data-src', tempProperty);
}

tempProperty = '';
var iterator = 0;

// select the container where pictures will be inserted
var injDiv = $$('div.imageswrapper');

// recursive function that triggers when a new image is loaded
function imgBomber() {
    // base case for recursion
    if (iterator > (imagesArray.length-1)) {
        return false; 
    }
    tempProperty = imagesArray[iterator].getProperty('data-src');
    imagesArray[iterator].removeProperty('data-src');
    imagesArray[iterator].setProperty('src', tempProperty);
    imagesArray[iterator].addEvent('load', function() {
        imagesArray[iterator].inject(injDiv);
        iterator++;
        imgBomber();
    });

} ;
imgBomber();
});

Answer №1

Upon reviewing the code, there are several issues that stand out. The main issue seems to be unidentified, so I will provide some feedback and suggestions until the specific problems are identified and shared (or provided through a jsfiddle).

  • Running the code in domready may lead to images being downloaded based on the src property before you initiate data loading. Consider sending data-src directly from the server beforehand.

  • The major problem lies in:

    var injDiv = $$('div.imageswrapper');
    returning a collection instead of a single element, making it incompatible with inject. Use
    var injDiv = document.getElement('div.imageswrapper');
    instead.

  • Issues arise with the load events and cross-browser compatibility for .addEvent('load'). It's essential to clean up after executing these events, especially in IE < 9 where load triggers unnecessarily. Additionally, lacking onerror and onabort handlers can halt the loader on unexpected responses like 404 errors.

  • Avoid using data-src for storing data as it can be slow. Utilize MooTools Element storage methods such as el.store('src', oldSource), el.retrieve('src'), and el.eliminate('src') for faster operations.

  • Be cautious about exposing iterators to outer scopes to prevent potential issues.

  • Utilize MooTools API functions like .set() and .get() over .getProperty() and .setProperty().

  • Avoid using for (var i) iterators for asynchronous operations to ensure correct index referencing. Instead, consider using MooTools' .each(fn(item, index), scope) method from Elements / Array.

It appears your problem has been addressed on multiple levels by solutions such as my pre-loader plugin which offers framework-agnostic image loading features with options for parallel or pipelined downloads along with progress events. You can view an example at http://jsfiddle.net/dimitar/mFQm6/ to see the functionalities described.

MooTools also provides solutions like Asset.js - for handling assets including images. Take inspiration from their implementation available at https://github.com/mootools/mootools-more/blob/master/Source/Utilities/Assets.js.

For a demonstration leveraging my pre-loader class, check out this example: http://jsfiddle.net/dimitar/JhpsH/

(function(){
    var imagesToLoad = [],
        imgDiv = document.getElement('div.injecthere');

    $$('.imageswrapper img').each(function(el){
        imagesToLoad.push(el.get('src'));
        el.erase('src');
    });

    new preLoader(imagesToLoad, {
        pipeline: true,
        onProgress: function(img, imageEl, index){
            imgDiv.adopt(imageEl);
        }
    });

}());

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

Using jQuery, you can easily insert a <span> tag around selected text and then save this modification permanently in a local HTML file

I have compiled notes in an HTML file stored on my local computer, with the intention of keeping it solely for personal use. For instance, I have a snippet like this: <p> this is an example text</p> My goal is to highlight the word "example" ...

The sidebar.querySelector method is not working as expected

Attempting to assign an 'active' class to the clicked 'nav-link' element in order for it to stay active on the next page the user navigates to. Encountering an issue with sidebar.getElementsByClassName is not a function showing up in t ...

Using TypeScript: creating functions without defining an interface

Can function props be used without an interface? I have a function with the following properties: from - HTML Element to - HTML Element coords - Array [2, 2] export const adjustElements = ({ from, to, coords }) => { let to_rect = to.getBoundingC ...

How to populate a database with Facebook data by utilizing AJAX post and PHP

I've been developing a Facebook Canvas game and had it running smoothly on my localhost along with a local database via phpMyAdmin. However, after moving it online, I've encountered an issue with the database. Previously, the game would grab pla ...

Navigating routes for a module sourced from NPM: Best practices

Looking for guidance on loading Angular routes from an NPM module? Take a look at this snippet from my app.module.ts file: import { HelloWorldModule } from 'hello-world-app-npm/hello-world-app.umd.js'; // Loading module from NPM const routes = ...

Should you construct a fresh element using JavaScript, or opt to reveal a concealed one using CSS?

What are the benefits of using the following approach: var target = document.getElementById( "target" ); var newElement = document.createElement( "div" ); $( target ).after( newElement ); compared to just hiding the newElement div with CSS and showing ...

In the absence of a value

In my code, I've implemented a functionality that saves the user's input into local storage and displays it in a specific ID. However, I want to make sure that if the input field is left empty, the user is prompted to enter their name. function ...

Finding all parent IDs from a given child ID within a nested JSON structure that contains children can be achieved by recursively

function loadKendoTreeView() { if ($("#treeview").data("kendoTreeView") != null) { $("#treeview").data("kendoTreeView").destroy(); $("#treeview").empty(); } var jsonData = [{ "Id": "239297d8-5993-42c0-a6ca-38dac2d8bf9f", ...

The function parseFloat in Javascript can be used to subtract two numbers, returning an integer value

Apologies for the inconvenience, but I could really use some assistance. I attempted to convert a string into a decimal and was successful, although I encountered an issue: number = document.getElementById("totalcost").innerHTML; //String that rep ...

Do you notice a discrepancy in the number returned by Javascript's Date.getUTCDate() when the time component is set to

Consider the following code snippet: const d = new Date('2010-10-20'); console.log(d.getUTCDate()); If you run this, the console will output 20. However, if you modify the code like so: const d = new Date('2010-10-20'); d.setHours(0, ...

What is the most effective method for transferring an error message from the server backend to the vue frontend?

I'm currently working on implementing error handling for a Vue/Vuetify application. The challenge I'm facing involves using external pagination for a datatable that connects to an API with rate limiting restrictions. If users exceed the limit, I ...

The function of jQuery's .prop('defaultSelected') appears to be unreliable when used in Internet Explorer 9

Below is the code I am currently using: $selects = $('select'); $selects.val( $selects.prop('defaultSelected')); The purpose of this code is to reset the values of all select elements on my webpage. However, I am facing an issue in IE ...

javascript monitoring numerous socket channels for echoes

Currently, I am in the process of developing a chat application. On the server side, I am utilizing: php, laravel 5.4, and pusher. On the client side, I have incorporated vue.js along with laravel-echo. Initially, I successfully created a "public chat roo ...

Node.js server allows for accessing AJAX requests seamlessly

I need to send a parsed AST of JavaScript code to a server for processing, and then receive a list of completions back. However, when I log the AST to the client console before sending it, the structure appears like this: [ { "id":0, "type":"Program", "ch ...

When attempting to make a GET request, Express/Mongoose is returning a null array

I am having trouble retrieving the list of books from my database. Even though I have successfully inserted the data into Mongoose Compass, when I try to fetch it, all I get is an empty array. //Model File import mongoose from "mongoose"; cons ...

React Component: Issue with conditional "if else" statement not refreshing in return statement

Starting out in React and the front-end field with minimal experience. Currently attempting to dynamically change the color of the "fill" property in a polygon element using React. If the percentage is greater than 50, I want the color to be green; otherw ...

Error in executing a function within an asynchronous function sequence

Whenever a user logs in, I want to update their data in Firestore. However, the code I am using does not seem to work as expected. It fails to create a custom User object from the firebase.User. Can anyone help me understand why this is happening and how ...

Load Vue dynamically to implement reCAPTCHA script

I am looking for a way to dynamically load a script like recaptcha specifically within the Register.Vue / login.Vue component. <script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer> </s ...

Tips for passing a timestamp to a Postgresql DB using a Button in a Form instead of a traditional rails time_select box

I am currently developing a CAD App in Rails 4 with Ruby 2. The goal is to provide users with a button on the screen to log an on-scene time and clear scene time, especially since most users will be using touch screen computers. Instead of using the defaul ...

modifying input field with radio button selection in Jquery

Is there a way to set the input field to have a default value and then change it, or disable it with a different value? $("#tax").value(19).prop("disabled",false); $("#tax").value(0).prop("disabled",true); <script src="https://ajax.googleapis.com/aj ...