简体   繁体   中英

How do I make a jQuery function execute on cloned elements?

I am trying to build a page with cascading dropdowns using jQuery where a cloned set of dropdowns is created once the last dropdown is changed in the current set. I want this process to continue up to 10 times, but I keep getting stuck with the second cascade set not working.

Here is a truncated version of the HTML markup I'm testing 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 shortened 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);
    });
});
});

And here's the JSfiddle I made with the full code:

http://jsfiddle.net/w8oatxxd/

As you can see, the dropdowns are cloned once the Size is selected and the first dropdown works in the cloned set, but the cascade breaks and the second dropdown in the cloned set doesn't populate. I've been searching everywhere and can't seem to figure this out. It will probably a very simple solution, but nothing I've tried has worked.

Please help!

You are trying to use listeners on DOM elements that don't exist yet. You need to use jQuery .on or add the listeners to the new DOM elements after to clone them. Instead of doing $.each($('.brand')... just try to do $('body').on('change','.brand',function(){ . Should work about the same. I'll mess with your fiddle.

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

I think you might need to look at your newRow JS for naming issues, but this answers and fixes your question.

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

Maybe like this : http://jsfiddle.net/OxyDesign/wndhqt1s/

JS

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);
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM