简体   繁体   中英

How can I make this code work better?

I recently asked a question about manipulating the html select box with jQuery and have gotten this really short and sweet code as an answer.

$("#myselect").change(function (event) {
    var o = $("#myselect option:selected"),
    v=o.text(),
    old = $("#myselect option:contains('name')"),
    oldv = old.html();

    oldv && old.html( oldv.replace('name: ', '') );
    o.text('name: ' + v);
});

I have one problem. This code doesn't work on multiple categories and I can't seem to wrap my mind around how it can be done. So, I made the obvious changes to it:

$("select").change(function (event) {
    var foo = $("select option:selected"),
        bar = foo.text(),
        cat = foo.parent().attr("label"),
        old = $("select option:contains('" + cat + "')"),
        oldbar = old.html();

    oldbar && old.html( oldbar.replace(cat + ': ', '') );
    foo.text(cat + ': ' + bar);
});

This now works on multiple optgroups/categories but has led to another bug. A more problematic one, at that.

It happens when you click from one category to another. Check it out on jsFiddle .

The problem with the last snippet is it uses the name of the current category to locate the last selected label to flip back. Instead, how about searching for the ":", (this won't work if you have ":" in one of your options), and then replacing that part of the string.

change line 5 to:

, old = $("select option:contains(':')")

and line 8 to:

oldbar && old.html(oldbar.replace(oldbar.substr(0, oldbar.indexOf(':') + 2),''));

Let me know if that's not working for you!

Edit: as an afterthought, you might consider adding this line

$('select').change(); 

As well, somewhere in the $(document).ready() event, so that when the page first renders the default value gets the prefix like (I think) you want.

I've renamed the variables since it is really a good habit to get into naming your variables and functions with meaningful names so you can juggle in your memory what is going on.

$("select").change(function () {
    // We immediately invoke this function we are in which itself returns a function;
    // This lets us keep lastCat private (hidden) from the rest of our script,
    // while still giving us access to it below (where we need it to remember the
    // last category).
    var lastCat;
    return function (event) {
        var selected = $("select option:selected"), 
            selectedText = selected.text(),
            cat = selected.parent().attr("label");
        if (lastCat) { // This won't exist the first time we run this
            oldSelection = $("select option:contains('" + lastCat + ":')");
            oldHTML = oldSelection.html();
            oldHTML && oldSelection.html(oldHTML.replace(lastCat + ': ', ''));
        }
        selected.text(cat + ': ' + selectedText);
        lastCat = cat; // Remember it for next time
    };
}()); // Be sure to invoke our outer function (the "closure") immediately, 
// so it will produce an event function to give to the change handler, 
// which still has access to the variable lastCat inside

Here's a shot in the dark. At first blush, it appears you're not saving the previous selection and you're using the selection which triggered the event in your oldbar && old.html( oldbar.replace(cat + ': ', '') ); line. You need to save the category of the previous selection in a separate var.

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