What is this jQuery doing? - javascript

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.

Related

Object definition in old Javascript

I came accross a following piece of code and i got confused and unable to understand the syntax used.
I would need help to break some hightlighted
let HT = HT || {}; //What is this syntax and what does it do ?
//Are we adding an Hexagon object to the object HT ?
HT.Hexagon = function(id, x, y) {
}
//Are we adding an object named Orientation to the object Hexagon ?
HT.Hexagon.Orientation = {
Normal: 0,
Rotated: 1
};
//Are we adding an object named Static to the object Hexagon ?
HT.Hexagon.Static = {
HEIGHT:91.14378277661477,
WIDTH:91.14378277661477,
SIDE:50.0,
ORIENTATION:HT.Hexagon.Orientation.Normal,
DRAWSTATS: false
};
How can one convert this piece of code to the modern ES6 classes ?
The first line code is using the or operator.
The operator checks first the expression on its left side - in this case the HT (it's probably an existing object.) If the expression is true e.g. holds a value like an object a number or a string etc, the expression will be assigned to the variable.
If HT does not hold any value which means it is false. Than it assign's the expression on its righte side - in this case an empty object.
The answer for your other three question is yes.
And it's not old JS at all.

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

Toggling button text using ternary operator

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().

Understanding the example code from http://javascriptissexy.com/javascript-is-super-sexy/

I'm perplexed as to how to follow the flow of this code.
As is probably obvious, I'm currently a relative beginner to JavaScript.
As I understand it:
the first two lines declare 2 global variables, "sexy" and "JavaScript", but don't define them.
Line 3: define the function "sexy" which takes zero arguments.
Line 4: what happens when sexy is invoked. I find the syntax on this line confusing. I read it as something like: if "ugly. Rails is HOT." is true, then pass "Sexy!" to sexy.sexy. Otherwise, pass "no Python." to sexy.sexy.
Line 6: defines the object named Javascript and its contents.
Line 7: key "sexy" : value = variable sexy,
Line 8: key "is" : value = function "sexAppeal"
Line 9: argument passed to function sexAppeal is true.
Line 10: if arguments[0] is false, then console.log "JavaScript is " + whatever this.sexy() evaluates to.
Last line: invoke the "is" function inside of the JavaScript object with zero arguments.
I'm not quite sure how to follow this all from the function call on the last line, to the point where it console.logs the final output.
Any narration would be greatly appreciated. Thank you!
var sexy,
JavaScript;
function sexy() {
return this.sexy ? ("ugly. Rails is HOT.","Sexy!") : "no Python.";
}
JavaScript = {
sexy:sexy,
is:function (sexAppeal) {
sexAppeal = true;
if (!arguments[0]) {
console.log("JavaScript is " + this.sexy());
}
}
};
JavaScript.is();
Narration in comments:
var sexy, // declare a variable named `sexy`
JavaScript; // and one named `JavaScript`
function sexy() { // declare a function named `sexy` which overrides the `sexy` variable
return this.sexy ? // ternary operator condition is that `this.sexy` have a truthy value
("ugly. Rails is HOT.","Sexy!") : // comma operator, equivalent to 'Sexy!'
"no Python."; // falsy result
}
JavaScript = { // initialize JavaScript to an object (with two properties)
sexy:sexy, // property `sexy` references the function above
is:function (sexAppeal) { // property `is` references this unnamed function defined right here
// inside the function the first argument can be referenced as `sexAppeal`
sexAppeal = true; // override the value of `sexAppeal` to be `true`
if (!arguments[0]) { // `arguments[0]` is the original value of the first argument
console.log("JavaScript is " + this.sexy()); // prints `Javascript is Sexy!`
}
}
};
JavaScript.is(); // call the unnamed (`is`) function above with `this === JavaScript` and `sexAppeal === undefined`
Extra: the ternary condition is true because this.sexy === JavaScript.sexy which is a function (and functions are objects which all evaluate to true).
I think what you've got most problem with is this:
function sexy() {
return this.sexy ? ("ugly. Rails is HOT.","Sexy!") : "no Python.";
}
which indeed defines global function sexy. Let's change this code a little, so it will start to make sense.
JavaScript = {
sexy: function() {
return this.sexy ? ("ugly. Rails is HOT.","Sexy!") : "no Python.";
},
is:function (sexAppeal) {
sexAppeal = true;
if (!arguments[0]) {
console.log("JavaScript is " + this.sexy());
}
}
};
All better. While now the function isn't global, it shows us what it does - if this.sexy is defined within this object (which it is), returns ("ugly. Rails is HOT.","Sexy!") - which enumerates to "Sexy!" due to , operator (try in console 0,1 or 1,0 or a,b).
With the default syntax, we would be able to create any amount of objects (and "classes") and make the function sexy access their properties.
Now what happens in the Javascript block.
The first thing is is. Is is a reserved word and shouldn't be used - while it will work in Chrome, it won't in IE (i'm fairly sure it can't be used in IE8, at the moment my local IE updated itself, so can't really test it). (looking at documentation can't confirm that is is indeed a reserved keyword, though I'm fairly sure IE complained about it. Maybe it's my dementia kicking in). What is interesting with is function is that it shows that parameters in JS can be overloaded. Meaning:
var a = function()
{
arguments[0] = 'a';
console.log(arguments[0]);
}
a();
will output 'a';
Your thought process was correct - hopefully my explanations over the bits make sense

Best Way for Conditional Variable Assignment

Which is the better way for conditional variable assignment?
1st method
if (true) {
var myVariable = 'True';
} else {
var myVariable = 'False';
}
2nd Method
var myVariable = 'False';
if (true) {
myVariable = 'True';
}
I actually prefer 2nd one without any specific technical reason. What do you guys think?
try this
var myVariable = (true condition) ? "true" : "false"
There are two methods I know of that you can declare a variable's value by conditions.
Method 1: If the condition evaluates to true, the value on the left side of the column would be assigned to the variable. If the condition evaluates to false the condition on the right will be assigned to the variable. You can also nest many conditions into one statement.
var a = (true)? "true" : "false";
Nesting example of method 1: Change variable A value to 0, 1, 2 and a negative value to see how the statement would produce the result.
var a = 1;
var b = a > 0? (a === 1? "A is 1" : "A is not 1") : (a === 0? "A is zero" : "A is negative");
Method 2: In this method, if the value of the left of the || is equal to zero, false, null, undefined, or an empty string, then the value on the right will be assigned to the variable. If the value on the left of the || does not equal to zero, false, null undefined, or an empty string, then the value on the left will be assigned to the variable.
Although the value on the left can be an undefined value for JS to evaluate the condition but the variable has to be declared otherwise an exception will be produced.
var a = 0;
var b = a || "Another value";
An alternative way of doing this is by leveraging the ability of logical operators to return a value.
let isAnimal = false;
let isPlant = true;
let thing = isAnimal && 'animal' || isPlant && 'plant' || 'something else';
console.log(thing);
In the code above when one of the flags is true isAnimal or isPlant, the string next to it is returned. This is because both && and || result in the value of one of their operands:
A && B returns the value A if A can be coerced into false; otherwise, it returns B.
A || B returns the value A if A can be coerced into true; otherwise, it returns B.
Answer inspired by this article: https://mariusschulz.com/blog/the-and-and-or-operators-in-javascript
PS: Should be used for learning purposes only. Don't make life harder for you and your coworkers by using this method in your production code.
You could do a ternary, which is a lot shorter (and no darn curly braces):
var myVariable = (true) ? 'True' : 'False';
Another cool thing is that you can do multiple assignment based on a conditional:
let [long_str, short_str] = a.length > b.length ? [a, b] : [b, a]
Third way when you are storing only true false in variabel then use
var myVariable =(condition_written_in_if);
Just for completion, there is another way in addition to all the others mentioned here, which is to use a lookup table.
Say you have many possible values, you could declaratively configure a Map instead of using an if, switch or ternary statement.
Object map = {
key1: 'value1',
key2: 'value2,
keyX: 'valueX'
};
var myVariable = map[myInput];
This works even for booleans:
Object map = { true: 'value1', false: 'value2 };
var myVariable = map[myBoolean];
For booleans you would probably do it the 'normal' way though with logic operators specifically designed for that. Though sometimes it can be useful, such as:
portability: you can pass a map around
configurability: maybe the values come from a property file
readability: if you don't care it's a boolean or not, you just want to avoid conditional logic and reduce cognitive load that way
Note there is some overlap between the advantages using a lookup map and advantages of using a function variable (closure).
The first solution uses only one assignment instead of 1,5 by average in the second code snippet. On the other hand the first code snippet is less readable as people not familiar with JavaScript might not realize that the scope of a variable is not block oriented by function oriented - on other languages with C-like syntax myVariable would not be accessible outside if and else blocks.
In other words both solutions have disadvantages. What about ternary operator:
var myVariable = condition? 'True' : 'False';
or if you don't care about the camel-case (although I understand this is just an example, not a real code);
var myVariable = (!!condition).toString();
If you tired of ternary operator then use IIFE
Another way would be to use Immediately Invoked Function Expression. The good thing about it is that it can hold some logic and can be encapsulated from the outside world.
const direction = "n";
const directionFull= (() => {
switch(direction ){
case "n": return "north";
case "s": return "south";
case "w": return "west";
case "e": return "east";
}
})()
console.log(directionFull);
I would prefer 2nd option too, no technical reason but for the sake of easy to read code, readability is very important in code.
If you see the second option, from processing point of view only one check will ever be executed, saved some very minute processing time, so there is only one check in second case.
It depends on the use for me. If I have code that I only want to run if true, but with no extra code for false, I'll use the second. If I want to execute some code on true, and different on false, I use the first. It all depends on use, but the general rule for me is to write once. Keep it clean, keep it simple, and keep it short
Maybe you simply need && operator to check if boolean is true, if it is, assing "myVariable" to true.
var myVariable = 'False';
true && myVariable = 'True';
If all you need to do is convert a boolean to a string, you should do so explicitly:
var myBool = true;
var myVariable = myBool.toString(); // 'true'
// '' + myBool, ''.concat(myBool), etc. also work
If it's important that the first letter be capitalized, as in your example, that is not difficult to do; see e.g. this answer.
Another approach with Map and Object: (Maps are more flexible with key types and Objects are more readable IMHO)
const condition_var = 'e'
const options1 = new Map([ ['n','north'],['s','south'],['e','east'],['w','west']])
const myVar1 = options1.get(condition_var) || null
const options2 = {n:'north', s:'south', e:'east', w:'west'}
const myVar2 = options2[condition_var] || null
console.log(myVar1)
console.log(myVar2)

Categories

Resources