Albert
Albert

Reputation: 507

jQuery - loop through each element

I have a script that transforms selected option from the dropdown list into a link.

Each dropdown is contained inside <li> – and there can be unlimited duplicates added through my script, so it makes kind of difficult to give each <li> an id-selector.

HTML:

<ul class="mylist">
    <li>
        <select>
            <option value="http://google.com">Google</option>
            <option value="http://twitter.com">Twitter</option>
        </select>
    </li>
</ul>

Part of my script that is responsible for adding more duplicates and transforming dropdown list into link.

$(document).keydown(function (e) {
    var key = e.which;
    if(key == 107) {
        $('.mylist').append("<li><select><option value='http://google.com'>Google</option><option value='http://twitter.com'>Twitter</option></select></li>");
    }
});

$("button").click(function () {
    var which = $("select").val();
    var text = $('select option:selected').html();
    $("select").replaceWith("<a href='" + which + "'>" + text + "</a>");
});

I need to change my script so it transforms EACH dropdown <select> into EACH selected value, because now it transforms EVERY dropdown into the first dropdown's value. How do I do that if I have no id-selectors, since unlimited duplicates may be added?

Upvotes: 1

Views: 3664

Answers (4)

Jeffers
Jeffers

Reputation: 29

The answer is simple enough, but there's a lot of ways to optimize this.

So assuming $("button") refers to some button that occurs later (you should give it an ID or class and reference that btw), you can do this:

//Document ready adds closure
$(document).ready(function () {
    var $mylist = $('.mylist');
    //Place event handler on body or even $mylist to reduce polling processing (compared to entire document)
    //Use 'keyup' instead of 'keydown' since it won't fire continuously if held down
    $('body').on('keyup', function (e) {
        var template = $('<li><select><option value="http://google.com">Google</option><option value="http://twitter.com">Twitter</option></select></li>');
        //If key pressed is '+' symbol - 107 is keypad '+', 187 is keyboard '+'
        if(e.which === 107 || e.which === 187) {
            //Since $('.mylist') is the never-changing container, it's better to cache the variable globally and reference it on every keypress
            $mylist.append(template);
        }
    });

    $('button').on('click', function () {
        $("select").each(function (index, el) {
            //.children() is a little bit less intensive than .find()
            var $select = $(el),
                $selectedOption = $select.children('option:selected'),
                selectedValue = $selectedOption.val(),
                selectedText = $selectedOption.text(),
                replacementLink = $('<a href="' + selectedValue + '">' + selectedText + '</a>');

            //Replace select with link
            $select.replaceWith(replacementLink);
        });
    });
});

It's better to use .text() than .html() for the selected option text in this instance because it cuts down on XSS vulnerabilities (stops potential user input reflection), and grabbing attributes from the cached variable is a little better for performance.

One more thing: if you are going to add any event handling to the selects themselves, you'll need to do it 'live' like this to account for selects that get added later:

$mylist.on('change', 'select', function (changeEvent) {
    //whatever
});

Good luck dude!

Upvotes: 1

oshell
oshell

Reputation: 9123

Allthough jQuery is providing an each function it is relatively slow compared to the native javascript for loop and you should avoid using it. Native for loop is up to 100x times faster. You can use the native function and eq() to get certain elements within the loop.

var select = $("select");
$("button").click(function () {
    for (var i = 0; i < select.length; i++) {
        var value = select.eq(i).val();
        var text = select.eq(i).find('option:selected').html();
        select.eq(i).replaceWith("<a href='" + value + "'>" + text + "</a>");
    });
});

Upvotes: 1

meskobalazs
meskobalazs

Reputation: 16051

Use the .each() function.

$("select").each(function (index, value) {
    // ...
});

Upvotes: 1

Raidri
Raidri

Reputation: 17560

Use jQuery.each():

$("button").click(function () {
    $("select").each(function() {
        var value = $(this).val();
        var text = $(this).find('option:selected').html();
        $(this).replaceWith("<a href='" + value + "'>" + text + "</a>");
    });
});

Upvotes: 2

Related Questions