Toggling button text using ternary operator - javascript

I am trying to toggle button text by using ternary operator but it is not working.
<button type="button" id="ter" >Bar</button>
$("#ter").click(function(){
$(this).text() = 'Bar' ? 'column':'Bar';
});
Is this possible to do this way? and what part I am doing wrong? I know there many other ways to achieve this but I just need to know if it is possible in this method or not?

You could also try this:
$("#ter").click(function(){
var newText = ($(this).text() == 'Bar') ? 'column':'Bar';
$(this).text(newText);
});
This checks if the current text is equal to 'Bar' with $(this).text() == 'Bar'. If it is, it sets the variable newText to 'column' (or vice versa). The second line replaces the old text with the new text.

You are using the ternary operator wrong. It goes:
[statement] ? [code when true] : [code when false]
You're basically testing if('Bar') right now which will always return true.

You're doing it wrong, you could instead use this approach:
$("#ter").click(function(){
$(this).text(function (i, t) {
return t === 'Bar' ? 'column':'Bar';
});
});
The reason it didn't work is because:
You were trying to assign a result to $(this).text() (using =) instead of comparing (== or ===), and
Not returning anything to update the text
It's important to note that with jQuery the text() method (and most others) when called with no arguments is a getter (it gets the current value), but to use it as a setter you have to pass an argument, either directly ($(this).text('foo')) or using the anonymous function ($(this).text(function(){ return 'foo'; })). Calling the getter, and comparing that retrieved value (or trying to assign to it) does not act as a setter.
In the anonymous functions available to jQuery methods, the first argument (here called i, but the name is irrelevant, it's always the first argument) is the index of the current '$(this)' object in the collection returned by jQuery, the second argument (here called t, but again the name is irrelevant) represents the current (pre-manipulation) value found by the method.
References:
text().

Related

Using ternary operators in a function with javascript

I am new to Javascript and sort of working through the weeds on these ternary operators. I have this small code segment:
const x = MSys.inShip ? 'ship launch' : '';
if (x != '') {send_command(x);}
While this works efficiently enough I am curious as to if it can be rewritten inside of the function call. Something like the following:
send_command(const x = MSys.inShip
? 'ship launch'
: MSys.alert("You aren't in your ship!);
This may not make sense with the current example but it's the best idea I had at the time. Basically, I like the shorthand of the ternary style for easy if/then conditionals but I don't like how it's tied to a variable which must then be called. I'm looking for a way to use that shorthand without having to tie to a variable.
Finally, the purpose of this is to see if you are in the ship and if you are, launch. If you aren't don't do anything at all or just send an alert message.
I am curious as to if it can be rewritten inside of the function call.
Yes, it can. But, if you do it there, then there is no need for a variable. You would be passing the function's argument directly inline.
Having said that, you can't pass that MSys.alert() statement as the "else" value because it will be executed in all cases. You'd have to pass a value there that the function can use as its input argument
send_command(MSys.inShip ? 'ship launch' : 'some other string');
Here's an example:
function foo(x){
console.log(x);
}
// If a random number is even, pass "even". If not, pass "odd"
foo(Math.floor(Math.random() * 10) % 2 === 0 ? "even" : "odd");
An important distinction between your two approaches - The second approach will ALWAYS call send_command() whereas your first approach will conditionally call it.
This distinction will matter depending on your implementation of send_command, but it sounds like you want the behavior of the first approach.
Additionally, You can't declare variables using const in a function call. If you just pass in the ternary operator, you will end up calling send_command with either your string, or undefined (the return of calling alert() ).
However, as an answer to your question, yes you can pass the ternary operator to a function like any other value. The ternary operator is an expression that will return a value.
Technically, you could keep a variable (such as operation) below, which references which method you want to execute, depending upon some conditional. And then you could pass that variable method the variable string it should get.
So, as you can see, it can be done. But look at how much complication was added to the process, rather than just using a simple if else statement.
function test_logic ( inShip ) {
// if they are in their ship, the operation should be the send_command method
// otherwise it should be the window alert
var operation = inShip ? send_command : window.alert;
function send_command ( command ) {
console.log( command );
}
// give the operation the desired string
operation( inShip ? 'ship launch' : "You aren't in your ship!" );
}
console.log( "Not in ship test" );
test_logic( false );
console.log( "In ship test" );
test_logic( true );

Why can't I chain String.prototype.toLowerCase with underscore.js?

I think the issue is not with underscore.js, but rather with Native prototypes functions. It seems that one can only call them directly, not passing them as callbacks. Here's the code the I can't use and the error from my tests (using Mocha.js, only the relevant portion):
_.chain("INPUT").tap(String.prototype.toLowerCase)
// => TypeError: String.prototype.toLowerCase called on null or undefined
So tried this in Node's REPL :
String.prototype.toLowerCase("INPUT")
// => ''
I know one should call a prototype's function with .call or .apply, but why exactly ? And how can I pass this function as a callback ?
Prototype methods are using this internally to refer to the object that should get manipulated.
call and apply lets you specify the this value when calling a function.
String.prototype.toLowerCase.call('INPUT'); //input
If you want to bind a this value to a function so that it's invocation form doesn't matter, you can do it with _.bind or Function.prototype.bind.
var lowerCaseInput = String.prototype.toLowerCase.bind('INPUT');
lowerCaseInput(); //input
Now, calling _.chain on an object will wrap it in an underscore object and returns the wrapper and _.tap takes the result of the previous function in the chain as it's input. Right here we see it's not going to work since String.prototype.toLowerCase doesn't even expect arguments.
Not only this, but strings are immutable so you would have to do something like the following:
_.chain({ text: 'INPUT' }).tap(function (obj) {
obj.text = obj.text.toLowerCase();
}).value().text;
Additionally, if you use mixins, you can use a mixin that simply wraps toLowerCase.
_.mixin({
toLowerCase: function(str) {
// Add here any desired validation if wanted
return str.toLowerCase();
}
}, {
chain: false
});
After, you can do something like:
_.chain('HELLO_WORLD')
.toLowerCase()
.replace('_',' ')
.value()

Odd Javascript alert output

I have an odd problem. I'm trying to use Javascript to fetch me some values from a multidimensional array, and it's giving me some weird output.
Here is my code:
foo = [['3','4'],['5','6']];
for (bar in foo) {
baz = bar[0];
alert(baz);
qux = bar[1];
alert(qux);
}
Here is the output of the above:
// These are all alerts, by the way
0,undefined,1,undefined,$,f,$,c,e,a,c,l,c,l,i,i,n,a,s,l,i,c,o,a,p,g,e,g,e,i,n,c,o,e,r,e,m,f,l,p,i,h,e,r,g
Can somebody tell me what is happening?
Here is a jsFiddle of the problem: http://jsfiddle.net/Jey6w/
Edit:
Here is another jsFiddle, with another layer of "Inception": http://jsfiddle.net/8vyGq/
The output:
// Again, these are all alerts, and * signifies undefined
0**1**$ff$ceaacllcllinnassliicooappgeegeeinncooerremmfllpiiheergg
The JavaScript for ... in loop gives you the names of the object properties, not the values.
Don't use for ... in for real arrays. Use a numeric index or .forEach().
The reason you're getting your output is complicated and uninteresting, since you just shouldn't do that, but here's a start. The property names will be coerced to strings by the for ... in. Thus, on the first iteration, "bar" is the string "0", so ("0")[0] is just "0", and ("0")[1] is undefined because "bar" is a single-character string.
After that, your for ... in loop staggers into some other properties inherited from somewhere; perhaps you're using Prototype or something. The loop then alerts the first two characters of the names of all those other properties.
I could be wrong, but I think it's due to the fact that bar is returning a reference to a property within an object. Changing your selectors to foo[bar][0] works a treat.
foo = [['3','4'],['5','6']];
for (bar in foo) {
alert(foo[bar][0]);
alert(foo[bar][1]);
}​
In cases where your object is simply a multi-dimensional array, I would sway array from using the for in statement, as it can select unwanted properties. I would stick to the good old fashioned for(start, stop, increment)
foo = [['3','4'],['5','6']];
for (i = 0; i < foo.length; i++) {
alert(foo[i][0]);
alert(foo[i][1]);
}​
Update - jQuery
As there has been mention of jQuery's .each method I thought I'd also post an example of how it could be utilised. The jQuery's each method passes 2 optional parameters, indexInArray, and valueOfElement. Additionally, the jQuery documentation also states that
The value can also be accessed through the this keyword, but
Javascript will always wrap the this value as an Object even if it is
a simple string or number value
With this in mind, we could achieve the same results as previous example, using the following jQuery (jsFiddle):
var foo = [['3','4'],['5','6']];
$.each(foo, function() {
// 'this' is the context of the current item within the array
alert(this[0]);
alert(this[1]);
}​)​

What is this jQuery doing?

I would call myself an intermediate jQuery developer, but I'm confused about what this line (from Twitter's Bootstrap) is doing:
$tip.find('.help-popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
Specifically, the part between the square brackets. Can anybody explain it to me?
$tip // tip object
.find('.help-popover-title') // find elements of this class
// if the data inside the title variable is an object
// use the append method otherwise use html method
[$.type(title) == 'object' ? 'append': 'html']
(title) // lastly, execute the selected function and pass in the title var
The inner statement uses a ternary operator. It's basically a single line if..else statement
x = 5;
x === 5 ? true : false; // true
x === 4 ? true: false; // false
Since the selected method is inside the brackets, you can use a string to select a method
It's equalvelent to:
$tip['append'](title) === $tip.append(title)
The big concept here is that object properties can be accessed not just literally and directly but also with square brackets containing a String (literal or variable) with the name of the property. Also, functions are always properties of an object—even if only the global context.
First, check out value-based properties:
var myobj = {
animal: 'frog',
color: 'blue',
fly: function() {/*fly*/},
hide: function() {/*hide*/}
};
alert(myobj.animal); // alerts 'frog';
var prop = 'color';
alert(myobj[prop]); // alerts 'blue';
Then note that when the property values are functions it doesn't change anything. They are still accessed the same way:
myobj.fly() // run function fly
prop = 'hide';
myobj[prop]() // run function named in variable 'prop', which is 'hide';
So ultimately, the code fragment you posted is just checking the type of the title variable and choosing the appropriate function to make it a child of the found element. If the title is an object, append it. If it's not (it must be text) then use the html function instead. It was coded this way to save duplicating code or declaring a new variable.
Ternary operators are the expressive forms of normal procedural if statements (that is, they evaluate to something rather than controlling flow). The following example will show this:
if (a == 1) {return 'yes';} else {return 'no';}
return (a == 1) ? 'yes' : 'no';
VB's Iif() function and Excel's IF() worksheet function are exactly equivalent.
It's an inline if statement, otherwise called a ternary operator. Basically, if the type of title is 'object' then it's getting the index 'append', otherwise the index 'html'. Hope this what you meant by your question.

Difference between if (var.length >0){} and if (var){}

In javascript is there a difference between using
if (foo.length > 0) {
//run code involving foo
}
and
if (foo) {
//run code involving foo
}
If so, could someone please explain the difference and an example where they would not be the same?
Here's an example where they are not the same:
var x = [];
alert(x? 'yes' : 'no'); // displays "yes"
alert((x.length > 0)? 'yes' : 'no'); // displays "no"
The two are completely different. I'm assuming by the use of .length that var is a jquery object, in which case if(var) will always be true. jQuery will always return an object, but it may be empty. if(var.length>0) checks that the jquery object actually contains an element.
The former tests if var.length returns more than 0. The latter tests if the value of var is true.
You cannot necessarily use either one for all variables. For a boolean, if(var) makes more sense. For a string or array, if(var.length) makes more sense.
they're obviously different, the question is really just why are they different.
your first example is explictly checking that the length property of an object is greater than 0. if that is true it evaluates the content of the if statement.
the second example can only tell you if the variable is 'truthy', or 'falsy' (or as the great stephen colbert coined it, 'truthiness'). check out the wikipedia article on javascript booleans for detail.

Categories

Resources