substitute every item that is a part of a particular group

My current project involves creating an embedded widget. Users will be required to insert an anchor tag and JavaScript code on their page, which then dynamically renders content similar to how embedded tweets work.

<a href="http://localhost:3000/user/13"
        target="_blank"
        class="my-widget" 
        data-widget-type="profile" 
        data-widget-identifier="id" 
        data-identifier-value="13"
   >Sayantan Das</a>
</div>
<script src="//localhost/my-widget/js/widget.js" async ></script>

The idea is that the widget.js script would locate all elements with the class my-widget and replace them with an iframe.

widgets.js

!function(global, document) {
    global.MyWidgets = global.MyWidgets || {};

    for(let widgets = document.getElementsByClassName('my-widget'), i = 0; i < widgets.length; i++) {
        console.log(widgets)
        let element = widgets[i];
        let span = document.createElement('span');

        span.innerHTML = "Changed from widget " + i;
        element.parentNode.appendChild(span);
        element.parentNode.removeChild(element);
    }

}(window, document);

However, I am facing an issue where if I remove an element within the loop, the loop ends prematurely. For example, if there are two elements with the class my-widget, after removing one element, the loop only runs once. How can I ensure that all elements are properly replaced?

Answer №1

The reason for this behavior is that when you use the getElementsByClassName method, it returns a dynamic live HTMLCollection. This means that if you remove an element with the specified class from the DOM, it will also be removed from the collection.

To address this issue, you can either iterate through the collection in reverse order so that removing elements does not affect the ones before them, or you can use querySelectorAll(".my-widget") which returns a static NodeList instead of a live HTMLCollection.

Example of iterating backward:

for(let widgets = document.getElementsByClassName('my-widget'), i = widgets.length - 1; i >= 0; i--) {

Using querySelectorAll instead:

for(let widgets = document.querySelectorAll('.my-widget'), i = 0; i < widgets.length; i++) {

If you do not need to track the index (variable i), you can now use for-of loop with NodeLists on most platforms. More information and a polyfill for other platforms can be found in this answer.

for (const element of document.querySelectorAll('.my-widget')) {
    // Remove the `let element = ...` line

Answer №2

Implement document.querySelectorAll to determine the number of widgets present on the page

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

Issue with ajax form: success function is not functioning as intended

For my form submission, I am utilizing ajaxForm(options) to run some functions before submitting the form. Here is an example of the options that I have configured: var options = { target : '#output1', success : ...

Unable to adjust the width of a label element using CSS specifically in Safari browsers

Here's the issue I'm facing with my HTML code <input type="checkbox" asset="AAA" name="assets[AAA]" value="AAA" id="assets[AAA]" class="c_green" checked="checked"> <label for="assets[AAA]"></label> In my CSS, I have the follow ...

What is the optimal method for organizing MongoClient and express: Should the Client be within the routes or should the routes be within the client?

Which is the optimal way to utilize MongoClient in Express: placing the client inside routes or embedding routes within the client? There are tutorials showcasing both methods, leaving me uncertain about which one to adopt. app.get('/',(req,res) ...

The process of eliminating line breaks in javascript is not functioning as expected

I've been searching all over the place, experimenting with different methods, but I just can't seem to fix this issue.. var save_field = res[0]; var save_value = res[1]; save_value = save_value.replace(/\n/gm, '<br />'); con ...

Tips for utilizing the useContext hook in Next.js

I'm facing an issue with persisting information between different pages using nextjs and the useContext hook. Despite changing a variable in one page, it reverts back to its default value when navigating to another page. Below is a glimpse of the dir ...

Update $(img).offset() upon clicking and dragging the image

Whenever I click on an image, it moves to a random position. I want different sounds to play based on where the click occurs: Directly on the image Within 50px of the image More than 50px away from the image. To achieve this, I need to constantly updat ...

Exploring nested maps in JavaScript

I attempted to nest a map within another map and encountered an issue where the innermost map is being executed multiple times due to the outer map. The goal is to link each description to a corresponding URL (using # as placeholders for some links). Here ...

Creating smooth and natural movement of a div element using Javascript (rotating and moving)

After struggling to use jquery plugins for smooth motion with the div elements I'm working on, I've decided it's time to seek some assistance. I have a group of div elements that all share a class and I want them to move around the screen c ...

Postgres.js Date Range query failing to fetch any results

Recently, I have been utilizing the Postgres.js npm module to interact with a PostgreSQL database Below is the code snippet for executing the query: let startDate = '2020-01-28 08:39:00'; let endDate = '2020-01-28 08:39:59'; let table ...

Is this code correct for passing a variable to another form?

$("#delete").click(function() { deleterecord(); }); function deleterecord(){ var id = $("#iduser").val(); alert("aw"+id); var id = $('#iduser').attr(); e.preventDefault(); pressed = "delete" $.ajax({ ...

Utilize JavaScript to enable printing capabilities for multiple printers

Does anyone know how I can print two different types of documents on two separate printers without the print window showing up? I typically use "Always print silent" on Firefox to avoid the print window, but this won't work for printing on two differe ...

Simplified user interface for detecting radio button clicks

Currently working on a form that includes radio buttons, where an update function is triggered whenever there is a user input change. The challenge I am facing is how to incorporate user-friendly radio buttons with a larger button area encompassing both t ...

Struggling to get getInitialProps working in dynamic routes with Next.js?

I am encountering an issue. The return value from the getInitialProps function is not being passed to the parent component. However, when I console.log the values inside the getInitialProps function, they appear to be correct. Here is the code snippet: i ...

What is the best approach for organizing JavaScript/CoffeeScript in a Rails 5 project for optimal efficiency?

I am currently working on a web application with Rails 5.0.2 and I have a set of JS files for the project: https://i.stack.imgur.com/WYB23.png Each of my own JS files follows a similar pattern, like this: $(function () { var init = function () { ...

What is the method to set precise values on a range slider?

Currently, I am developing a PHP website that requires a slider for displaying the years of publications. In essence, I need the slider to navigate through the different years when the publications were released. // Database connection and other PHP code ...

Interested in trying out Express and socket.io for chatting?

I've successfully set up the chat application, but now I'm faced with a dilemma: how can I make the chat work on the default port:80, where my main site is hosted? One solution that comes to mind is using an iframe - but is there another way? B ...

When IntelliJ starts Spring boot, resources folder assets are not served

I'm following a tutorial similar to this one. The setup involves a pom file that manages two modules, the frontend module and the backend module. Tools being used: IDE: Intellij, spring-boot, Vue.js I initialized the frontent module using vue init w ...

When a JavaScript/jQuery open window popup triggers the onunload event after the about:blank page has been

Imagine you have a button that triggers a popup using window.open(): <button id = "my-button">Open window</button>​ You also want to detect when this popup window closes. To achieve this, you can use the following code: $('#my-button& ...

Having trouble with the Express.js app.post request functionality

I'm facing a challenge with the Express.js library. I've been attempting to set up a basic post request with the route. I have body-parser installed and am using it for the post data. If I specifically include app.post, it doesn't work, ...

The tension settings in Chart.JS appear unusual

I recently updated to ChartJS v4.0.1 and noticed a new option called tension for curving the line chart. However, I'm not satisfied with how it looks. The tension option ranges from 0 to 1, and I've experimented with different values to enhance ...