Any way to toggle between two strings using one piece of JavaScript?

25,679

Solution 1

Try:

something.val(something.val() == 'string1' ? 'string2' : 'string1');

It is called a ternary expression.

Solution 2

Look ma, no ternary operator!

The following works because Javascript short circuits boolean expressions.

If something == string1 then evaluate string2 -- since string2 is a truthy value and the next expression involves the OR operation there is no need to continue. Stop and return string2.

If something !== string1 then it will skip the next operand because if it is false, there is no point in evaluating the next operand (with AND). It will "jump" to the OR operation and return string1.

function toggleString(something, string1, string2) {
   return something == string1 && string2 || string1;
}

something.val(toggleString(something.val(), "string1", "string2"));

If you want the assignment done:

function toggleValue(something, string1, string2) {
   something.val(something.val() == string1 && string2 || string1);
}

toggleValue(something, "string1", "string2"); // something is a jQuery collection

In the end however, I would end up using the ternary operator because this solution might be unclear to other programmers. If you come from Java or other languages, you may expect the function to return a boolean because of all the boolean operators.

Solution 3

Another way to do it using object properties:

{ 'string1': 'string2', 'string2': 'string1' }[value]

As in the question:

something.val(
  { 'string1': 'string2', 'string2': 'string1' }[something.val()]
)

Solution 4

How about using @Daniel's code along with a jquery function:

$.fn.toggleVal = function (str1, str2) {
     return this.val(this.val() == str1 && str2 || str1);
};
$("input").toggleVal('string 1', 'string 2');

Solution 5

Though, the solutions with a ternary operator are the most readable, you could also use xor from Lodash:

x = _.xor([a, b], [x])[0]

For your specific case:

something.val(_.xor(['s1', 's2'], [something.val()])[0]);

Ref: https://lodash.com/docs/4.17.10#xor

Share:
25,679

Related videos on Youtube

Bojangles
Author by

Bojangles

Full stack web developer working with Node and React in Typescript and rather a lot of Rust.

Updated on January 22, 2022

Comments

  • Bojangles
    Bojangles over 2 years

    I want to do something like

    if(something.val() == 'string1')
    {
         something.val('string2');
    }
    else if(something.val() == 'string2')
    {
        something.val('string1')
    }
    

    But in one line of code. I can't quite remember how it's done, but it involves question marks and colons...

  • jcolebrand
    jcolebrand over 13 years
    why are you grabbing the jquery object back out?
  • jcolebrand
    jcolebrand over 13 years
    Ok, so you still have to assign to something in there somewhere. You didn't assign, you only compared.
  • jcolebrand
    jcolebrand over 13 years
    @Daniel ... yeah, I know that. My point was more like the ternary reads faster than that, and you still have to show the assignment in your clever post ;)
  • Bruce
    Bruce over 13 years
    +1 clever solution, though you should explain why this works.
  • Bojangles
    Bojangles over 13 years
    Thanks - a bit long winded for what I want as I'm doing this inline, but handy nonetheless!
  • dev-null-dweller
    dev-null-dweller over 13 years
    But this will set string1 even if value is string3, not only for string2
  • Cristian Sanchez
    Cristian Sanchez over 13 years
    @drachenstern: Since everybody else posted the ternary operator solution there really is no point in posting the same thing. This function will toggle between the two values based on the something. How he uses it (if at all) will be up to him -- it's would be up to him to modify it if he wants to make the function easier to use. Besides, something is meant to be a string (which are immutable) so I wouldn't be able to change it anyways. I'll add the explanation and add the version that does the assignment to satisfy you people.
  • Bojangles
    Bojangles over 13 years
    @dev-null-dweller this isn't a problem - I'm toggle the text in a button between 'Reply' and 'Cancel' :)
  • jcolebrand
    jcolebrand over 13 years
    lol@you people ... I added +1 for the clever. I just wondered if it was too clever as a two line post (ignoring brackets) ... and as for the "since everybody else posted the ternary" ~ it was what he asked for, and I was the second person to actually reply, but yeah, it was quite an avalanche of the same answer repeatedly.
  • fehays
    fehays over 13 years
    See my answer towards the bottom if you're interested in making this a jquery function so you can call $('input').toggleVal('str2','str2');
  • Cristian Sanchez
    Cristian Sanchez over 13 years
    There really is no benefit for using my solution over a ternary operator - I just thought it would be nice to offer an alternate version :). Nice though! isn't this already a jQuery object? So there is no need to wrap it with the $ function. Also, jQuery probably returns this when calling val as a setter, so you might be able to merge those two lines into a single one line return statement.
  • fehays
    fehays over 13 years
    Indeed you are correct. Thanks for the tip :) I will update the code. And I like yours over the ternary operator because question marks scare me :P
  • webLacky3rdClass
    webLacky3rdClass over 7 years
    This is an extremely question, but if you are going to answer it perhaps you could add an example implementation, you will notice most upvoted answers do. Cheers
  • Bojangles
    Bojangles over 7 years
    Very clever! I'd be tempted to use it but for two reasons; 1, it's not immediately clear what this code does and 2, nowadays I'd use ES6 destructuring like [ string2, string1 ] = [ string1, string2 ]
  • kolossal7
    kolossal7 over 7 years
    @Bojangles two switch two strings, yes, but how would you use ES6 features for your original question?