What is the best way to ensure a jQuery function runs on duplicated elements?

I have been attempting to construct a webpage featuring cascading dropdowns using jQuery. The goal is to generate a duplicate set of dropdowns when the last dropdown in the current set is altered. I aim for this process to repeat up to 10 times, but I constantly encounter an issue where the second set of cascading dropdowns fails to function.

Below is a condensed version of the HTML markup I am experimenting with:

<div class="cascadeDrops cascade-drops-0">
<label class="page1">Brand</label>
<div class="tooltips" title="Please select the brand.">
    <select class="brand" id="brand" name="brand" placeholder="Brands">
        <option value="">Select Brand</option>
        <option value="22 Days Nutrition">22 Days Nutrition</option>
        <option value="360CUT">360CUT</option>
        <option value="4 Dimension Nutrition">4 Dimension Nutrition</option>
    </select>
</div>
<br />
<br />
<label class="page1">Product</label>
<div class="tooltips" title="Please select the product.">
    <select class="products" id="products" name="products" placeholder="Products" disabled>
        <option value="">Select Product</option>
    </select>
</div>
<br />
<br />
<label class="page1">Size</label>
<div class="tooltips" title="Please select the size.">
    <select class="size" id="size" name="size" placeholder="Size" disabled>
        <option value="">Select Size</option>
    </select>
</div>

Here is the abridged test script:

jQuery(function($) {
var products = {
    '22 Days Nutrition': ['Select Product', 'Plant Protein Power', 'Protein Bars', 'Vegan Energy Bars'],
    '360CUT': ['Select Product', '360INTRA', '360LEAN', '360POST', '360PRE', '360SPORT', '360TEST'],
    '4 Dimension Nutrition': ['Select Product', 'Beta Alanine', 'CLA 1250', 'Creatine', 'Men\'s Pro-Vita', 'Omega-3 Plus', 'Pure Garcinia Cambogia Extract', 'Raspberry Ketone Green Coffee Bean', 'Yohimbe Bark', 'Yohimbine HCL'],
},
sizes = {
    '360INTRA': ['Select Size', '438 Grams'],
    '360LEAN': ['Select Size', '90 Capsules'],
    '360POST': ['Select Size', '1296 Grams'],
    '360PRE': ['Select Size', '640 Grams'],
    '360SPORT': ['Select Size', '384 Grams'],
    '360TEST': ['Select Size', '180 Capsules'],
    'Beta Alanine': ['Select Size', '100 Capsules', '180 Capsules'],
    'CLA 1250': ['Select Size', '120 Softgels', '180 Softgels', '90 Softgels'],
    'Creatine': ['Select Size', '100 Grams', '500 Grams', '1000 Grams'],
    'Men\'s Pro-Vita': ['Select Size', '2 Caplets'],
    'Omega-3 Plus': ['Select Size', '120 Softgels'],
    'Plant Protein Power': ['Select Size', '15 Servings', '22 Servings'],
    'Protein Bars': ['Select Size', '1 Bar', '12 Bars'],
    'Pure Garcinia Cambogia Extract': ['Select Size', '90 Capsules'],
    'Raspberry Ketone Green Coffee Bean': ['Select Size', '60 Capsules'],
    'Vegan Energy Bars': ['Select Size', '1 - 50g Bar', '12 - 50g Bars'],
    'Yohimbe Bark': ['Select Size', '100 Capsules'],
    'Yohimbine HCL': ['Select Size', '60 Capsules', '90 Capsules'],
}

$.each($('.brand'), function() {
    $(this).change(function() {
        var $products = $(this).closest('.cascadeDrops').find('.products');

        var brand = $(this).val(), prdcts = products[brand] || [];

        var html = $.map(prdcts, function(prdct){
            return '<option value="' + prdct + '">' + prdct + '</option>'
        }).join('');
        $products.html(html).removeAttr('disabled');
    });
});

$.each($('.products'), function() {
    $(this).change(function() {
        var $size = $(this).closest('.cascadeDrops').find('.size');

        var product = $(this).val(), szs = sizes[product] || [];

        var html = $.map(szs, function(sz){
            return '<option value="' + sz + '">' + sz + '</option>'
        }).join('');
        $size.html(html).removeAttr('disabled');
    });
});

var cls = $('.cascadeDrops').attr('class'), i = 0;
var newRow = $('.cascadeDrops').clone().attr('class', cls.replace(/cascade\-drops\-[0-9]/, 'cascade-drops-' + (i+1)));

$.each($('.size'), function() {
    $(this).change(function () {
        $(this).closest('.cascadeDrops').after(newRow);
    });
});
});

Here is the JSfiddle link with the complete code:

http://jsfiddle.net/w8oatxxd/

It is evident that upon selecting a Size, the dropdowns are duplicated, with the first set functioning correctly in the cloned version. However, the cascade malfunctions as the second dropdown in the cloned set fails to populate. Despite extensive research, I have yet to identify a solution. It is likely a simple fix, but all attempted solutions have been ineffective.

I am seeking assistance. Please, help!

Answer №1

Perhaps you could try it this way: http://jsfiddle.net/OxyDesign/wndhqt1s/

JavaScript

var maxRows = 9,
    currentRow = 0,
    clone = $('.cascadeDrops').clone();

$('body').on('change', '.brand', function() {
    var $products = $(this).closest('.cascadeDrops').find('.products');

    var brand = $(this).val(),
        prdcts = products[brand] || [];

    var html = $.map(prdcts, function(prdct){
        return '<option value="' + prdct + '">' + prdct + '</option>'
    }).join('');
    $products.html(html).removeAttr('disabled');
});

$('body').on('change', '.products', function() {
    var $size = $(this).closest('.cascadeDrops').find('.size');

    var product = $(this).val(), szs = sizes[product] || [];

    var html = $.map(szs, function(sz){
        return '<option value="' + sz + '">' + sz + '</option>'
    }).join('');
    $size.html(html).removeAttr('disabled');
});

$('body').on('change', '.size', function() {
    if(currentRow < maxRows){
        var parentRow = $(this).closest('.cascadeDrops'),
            cls = parentRow.attr('class'),
            newRow = clone.clone().attr('class', cls.replace(/cascade\-drops\-[0-9]/, 'cascade-drops-' + (++currentRow)));

        parentRow.after(newRow);
    }
});

Answer №2

If you are facing issues with using listeners on DOM elements that have not been created yet, consider using jQuery's .on method or adding the listeners to the new DOM elements after cloning them. Instead of using $.each($('.brand')..., try using

$('body').on('change','.brand',function(){
which should function similarly. I will take a look at your fiddle.

http://jsfiddle.net/w8oatxxd/1/

It seems like there may be naming issues in your newRow JavaScript code, but this solution addresses and resolves your concern.

$('body').on('change','.brand', function() {

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

How can I trigger a save dialog to allow downloading a file in AngularJS?

On the server, I have a directory containing files. When a client sends a file name, I successfully retrieve the file from the server. The response from the server is working fine so far. However, after receiving the response, I want to prompt the user to ...

What is the best way to utilize both the YouTube API and jQuery in order to successfully transfer a video file

I am currently working on utilizing the Youtube DataAPI in order to upload a video to our website's YouTube account. Although I have been referring to the documentation for Browser-based uploading and following its provided examples, I am facing troub ...

I'm not skilled in programming, so I'm not sure what the problem is with the code

While working on my Blogger blog, I encountered the need to add a fixed sidebar ad widget that would float along the screen. After trying multiple codes, I finally found one that worked. However, using the template's built-in variable functions led to ...

A dynamic homepage that transforms upon login, created without the use of any content management systems

I am embarking on creating a website with registration and login features without relying on any CMS, using only pure HTML/CSS and other necessary tools. My main confusion lies in how I can develop a homepage that can cater to any visitor by displaying rel ...

Issue with Checkbox Functionality Between Parent and Child Components in React.js

In the main component, I have four checkboxes. My goal is to display a value from a function in the child component based on whether each checkbox is checked or not. export default class App extends Component { constructor(props) { super(props); ...

Determine if the same origin policy is in effect

Is there a method to determine if the same origin policy is applicable to a URL before attempting to use ajax methods? Below is an example of what I currently have: function testSameOrigin(url) { var loc = window.location, a = document.create ...

Is it possible for PHP to not provide an image to HTML?

I'm currently facing an issue trying to display an image in HTML using a PHP script. Despite my best efforts, it's not functioning as expected :-( Here is the code snippet from my image.php script: <? $_GET['f'] = 'all_thre ...

Cakephp presents a challenge when trying to dynamically add HTML elements with JQuery and then later remove them dynamically

In the "garagecar/view/index.ctp" view page, we have a list of parts. These parts are initially populated with PHP when the page loads. Each part has a remove button that, when clicked by the user, triggers a controller link to delete the part. The JQuery/ ...

Node is not functioning properly with Discord.js as expected

Having some trouble catching errors in my code. I'm seeing a red line and an expression expected error behind the period after the catch command. Any suggestions? client.on('message', message => { let args = message.content.subs ...

Experiencing a problem with inline JavaScript onclick

I recently came across a fantastic pure javascript code for a smooth scrolling function, but I'm struggling with integrating it into an inline onclick function. My understanding of javascript is quite limited and I could really use some help... <d ...

When trying to use npm install, the process is being interrupted by receiving both 304 and 404

Whenever I execute the npm install command, my console floods with this: npm http fetch GET 304 http://registry.npmjs.org/is-arrayish 60ms (from cache) npm http fetch GET 304 http://registry.npmjs.org/spdx-license-ids 67ms (from cache) npm http fetch GET ...

Using ReactJS to Deconstruct Data within Class Components

I have a file named Context.js with the following content: const AppContext = createContext({ // ... color palette scheme color1: '#ADBDDB', color2: '#7F8EB2', color3: '#546287', color4 ...

What is the best way to create clickable text in an HTML string and set up an @click function in VueJS 2?

I have an array of strings that I want to transform by turning certain words like "User object", "Promise", etc into clickable links. Here is the initial array: var strings = ['This returns a promise containing a User Object that has the id', &a ...

What methods can I incorporate sophisticated logic into my dataform process?

Summary I am looking to enhance the functionality of my Dataform pipeline by introducing a layer of modularity (via JavaScript functions) that can identify when there is a disruptive change in the schema of my raw data source. This system would then autom ...

Spacing that separates elements vertically within a listing

I'm facing an issue with a list of elements arranged in a row that wraps onto a second line due to space constraints within the container. Is there a way for me to introduce additional spacing between the first and second line of these elements, bear ...

What is the best way to showcase navigation and footer on every page using AngularJS?

I'm in the process of building a Single Page Application. I've decided to create separate components for Navigation, Section, and Footer. The Navigation and Footer should be displayed on every page, while only the Section content changes when nav ...

Retrieve items from an array using indexes provided by a separate reference table

I am dealing with two different arrays. One array contains my data: var tab1 = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty"]; ...

The JSON data structure is not being maintained

I am facing an issue with updating the json object model values using the code below. Even after changing the values, it seems like the model is not getting updated. I tried removing the async code and that worked. Why does the async code not work in this ...

What are the steps to recursively transform a JavaScript object?

I am currently working on recursively transforming a JavaScript object, but I have encountered an issue. The problem is: if any object key has exactly two properties - 'label' and 'value', then the value should change to the label only ...

click event not triggering custom hook

I have developed a custom hook for fetching data and am struggling to implement it successfully. Below is my custom hook: import { useReducer } from "react"; import axios from "axios"; const dataFetchReducer = (state, action) => { ...