Is your Javascript loop malfunctioning?

I'm encountering a problem with a function I've created to tidy up some code. Take a look at the code snippet below for reference.

clean: function (e) {
    var
            els = null,
        i = 0;

    if (e === undefined) {
        e = this.cont;
    }

    els = e.getElementsByTagName('*');

    for (i=0;i<els.length;i++) {
        if (els[i].className.search('keep') === -1) {
            e.removeChild(els[i]);
        }
    }
    return this;
},

The parameter e represents a DOM element, and if not provided, it defaults to this.cont, which is another earlier stored DOM element within the function.

This function iterates through all child elements, checks if they do not contain the 'keep' class, and removes any that do not match the criteria.

Although everything seemed to be functioning correctly, there's an issue with removing all elements from an element that contains two images and two inputs, none of which have the 'keep' class. The loop only reaches 2 instead of 4 before stopping.

Any assistance on resolving this would be highly appreciated.

/* UPDATE */

Credit goes to @pimvb and @Brett Walker for suggesting the final updated code snippet shown below.

clean: function (e) {
    var
        els = null,
        i = 0;

    if (e === undefined) {
        e = this.cont;
    }

    els = e.getElementsByTagName('*');

    i = els.length;

    while (i--) {
        if (els[i].className.search('keep') === -1) {
            els[i].parentNode.removeChild(els[i]);
        }
    }

    return this;
},

Answer №1

Utilizing the .getElementsByTagName function yields a NodeList, which behaves like an array but is 'live'. This implies that it automatically updates when changes are made, such as removing a child element. Consequently, during iteration, the value of els.length fluctuates; for instance, if two children are removed, els.length will be 2 (due to having lesser elements after removal). In such scenarios, i == 2 may cause premature termination of the loop.

To address this issue and convert the NodeList into a static array that does not auto-update, you can employ the following method:

els = [].slice.call(e.getElementsByTagName('*'));

Brett Walker suggests an alternative approach - iterate in reverse:

http://jsfiddle.net/pimvdb/cYKxU/1/

var elements = document.getElementsByTagName("a"),
    i = elements.length;

while(i--) {
    var elem = elements[i];

    if(elem.className == "test")
        elem.parentNode.removeChild(elem);
}

This reverse iteration method begins at the last element, bypassing the live update issue with .length. By utilizing .length solely at the start and not during traversal, this workaround effectively eliminates the unexpected behavior.

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

Creating Duplicates of a Component in React

I am looking for a way to render multiple instances of the same component. Let's take a look at the component that needs to be duplicated (this is just a placeholder example, not the actual component): import React from 'react'; function Du ...

What is the most effective way to retrieve comments using Laravel Pagination without duplicates?

Lingering Issue: In the scenario where a user leaves a comment and subsequently opts to load more comments, they may encounter at least one duplicate comment. Root Cause: Using Laravel Pagination, the script leverages Axios to fetch the last 10 items. U ...

PugJS is failing to properly interpolate numbers from the JSON file

My goal is to display a list of interfaces retrieved from my router API, which is in JSON format. However, when using Pug, only the strings are being rendered and not the numbers. Here is the output (it displays correctly in HTML): em1 192.168.0.0/24 Addr ...

Failure in importing a custom CommonJS module

I developed a CommonJS module in project A using the following structure: const { WebElement } = require('selenium-webdriver'); const { By } = require('selenium-webdriver'); class VlElement extends WebElement { constructor(driver, ...

Is it feasible to save BoxGeometries or MeshLambertMaterial in an array using Three.js?

var taCubeGeometryArray = new Array(); var taCubeMaterialArray = new Array(); taCubeGeometryArray.push(new THREE.BoxGeometry( .5, .5, .5)); taCubeMaterialArray.push(new THREE.MeshLambertMaterial({map: THREE.ImageUtils.loadTexture( "image.png" )})); Could ...

Odd gap beside Bootstrap5 navbar that needs fixing

While working on a layout featuring a left-sided nav-bar menu, I encountered an odd blank space between the navbar and the main content area. Can anyone shed light on why this space appears and how to eliminate it? For reference, here is the code snippet: ...

What is the best way to serve individual static files in Express without revealing the entire "/static" directory?

For my new project, I am working on a simple setup that involves using JWT for authorization. The project is being served entirely through express, with no separation between frontend and backend. My goal is to dynamically serve specific HTML files based o ...

Patience is key as we await the arrival of the loaded data before making a return in AngularFire 0

I am working on a form that should only be submitted if the user provides a valid access key ($scope.access_key) - and each key can only be used once. Within my controller, I have the following method: $scope.verifyAccess = function() { var ref = new ...

Hovers and click effects for navigating through images

The website I'm currently working on is stipz.50webs.com. p.s. HOME functionality is not active at the moment. Having successfully implemented the onhover and onmouseout features, my next goal is to enhance the navigation effects for each div/img so ...

Visibility of the Protractor element is obscured

As someone new to Java Script and Protractor/Selenium testing, I am looking to explore a specific functionality. I am eager to test out the in-page auto scroll feature using Protractor. My initial idea was to use isDisplayed()).toBe(false);, but I realiz ...

Is it possible to change cases within a switch statement after one case condition has been satisfied?

I am currently working on implementing a game that involves rolling dice in Javascript/jQuery. The game has different "Phases" that the player must complete one by one without any interference from previous phases. The goal is to smoothly transition betw ...

Exploring the world of variable scopes in Node.js

I'm new to exploring the world of node.js, particularly trying to grasp the concept of asynchronous processing loops. Let's say I have an array called var counter = []; declared at the beginning of my server.js script. Next, I have a POST handl ...

implementing Angular2's Material Design with ES6

Can Angular2 Material2 be started with ES6? I have attempted to discover a solution but was unsuccessful. I also examined the git repository and noticed that all code is currently in TypeScript Does this mean we cannot use it with ES6? Is there an alte ...

When transferring JavaScript Array via Ajax to PHP, it results in a null response

I am attempting to send a JavaScript array to PHP, but the post data keeps returning null. Here is my JavaScript code: console.log($Seats); console.log($Seats.toString()); console.log(JSON.stringify({ $Seats })); var jsonStr = JSON.stringify($Seats); $.a ...

Encountering an issue with a MEAN application using Angular 2: The error message states "Cannot read property

As a first-time application developer, I am working on creating a system to manage Client profiles. Utilizing the Angular tour of heroes for the basic structure, I integrated mongodb and express components sourced from various online platforms. However, I ...

Having trouble opening an xlsx file with reactJS? Excel is having difficulty accessing the file

While attempting to download an xlsx file using reactJS, I am encountering an error message when trying to open the downloaded file: "Excel cannot open file 'file.xlsx' because the file format or file extension is not valid. Please verify that t ...

Activating view loading in AngularJS through child window authentication (OAuth)

I have tried implementing OAuth in AngularJS using Hello.js following what I believe is the best practice. However, I am encountering some issues with my current approach as described below: After injecting Hello.js into Angular and setting up the OAuth p ...

Two-way data bindings trigger the digest() function to iterate 10 times

I'm facing issues with angular binding and my experience level in this area is limited. I will be posting all related questions here. I have a piece of angularjs code that is triggering 10 digest() cycle reached errors. After researching similar posts ...

Error: Trying to access "dishes" property on an undefined object gives a TypeError

Need Assistance Urgently! I have developed a web application using react and integrated it with node js. In the app, I am required to pass the status of a dish to the DishDetail Component indicating whether it is marked as "Favorite" or not. If a dish is ...

Each time I load the page, it displays differently depending on the browser. I'm struggling to understand the reason

Trying to figure out how to make the navigation bar close when a link is clicked and directed to a section instead of a new page. When on a large screen, I want the nav bar to remain open but automatically close when on a small screen (for example, when th ...