jQuery hasClass not behaving - javascript

Why is this always returning false when it shouldn't be? How do I get it to behave?
var originalDiv = $(clickedButton).parent();
alert($(originalDiv).hasClass('.question_box_expanded'));

Remove the . before your class name. That's used for selectors only.
In order to debug this yourself, set a break point on that line. Then, step into the jQuery calls and look at what is happening. Somewhere along the way, it'd become obvious that the . was causing the issue.

Related

Javascript/jQuery variable, what is the proper way to use a var?

I am sorry if this is a dumb or easy question but I am fairly new to Javascript/jQuery. The past month I have really started to delve into the land of scripting and have seen two different, maybe three, ways people use var in Javascript/jQuery.
The way I use a var is like so,
var nav = $('nav');
nav.hide();
A very common way I have seen people use vars,
var nav = $('nav');
$(nav).hide();
From the answers,
var $nav = $('nav');
$nav.hide();
From what I have learned from searching through Google is what you typed inside the variable is saved there to later be used. I then figured if I wrote the $() around the var when I was using it, it would duplicate the $(). Yet both ways seem to work so I know it does not duplicate it and therefore can tell that it is the same thing.
Is there a correct way to use vars or are both equally the same and it doesn't matter?
I apologize again if this is a known answer and will be happy to remove it if someone can show me the original question but I couldn't find anything on it.
A great bit of information from an answer that I didn't mark as the answer but I find to be very important.
var element = document.createElement("div");
$("body").append(element);
$(element).hide();
In the example above, $(element) is necessary, because it takes a DOM
object and converts it to a jQuery selector. jQuery functions only
work on jQuery selectors, so you couldn't simply do element.hide().
$() creates a new jQuery object. If you save a jQuery object to a variable it is pointless to create another jQuery object from it, although it still works. You will often see people wrap variables that were previously created as jQuery objects in $() purely due to bad practice and either forgetting it's already an object...or not understanding what they just created in the first place
Perhaps you may have seen
var $nav = $('nav');
$nav.hide();
Using the $ prefix is a common practice to denote that the variable is a jQuery object for code readability mostly
Both variables store a jQuery object, which has access to jQuery methods. The latter approach unnecessarily tries to re-wrap that jQuery object in another jQuery object. The former approach is 'correct,' in that it's more efficient and less, to be frank, silly.
I've seen this issue in a lot of places. People use a lot of $ when they don't need to. Some use it just as an ornament on their variable name, which adds to the confusion.
First of all, there are no jQuery variables, only JavaScript variables, and as you said, variables store information. When the right hand side begins with $(), you're storing the results of a jQuery function in the variable. In the vast majority of cases, what you'll be storing is called a jQuery selector.
In the case of var nav = $('nav'), what you're storing is a selector representing all the elements in the DOM that are nav tags, i.e. that look like <nav></nav> (or equivalent).
As others already mentioned, the $(nav) is taking the stored selector, and creating a new selector out of it. It accomplishes nothing and is redundant, and is a poor programming practice, even if it is a pervasive one.
However, there is a similar syntax that makes sense:
var element = document.createElement("div");
$("body").append(element);
$(element).hide();
In the example above, $(element) is necessary, because it takes a DOM object and converts it to a jQuery selector. jQuery functions only work on jQuery selectors, so you couldn't simply do element.hide().
As I mentioned at the top, some people also use $ as a decorator on their variable names, e.g. var $selector = $("nav"). The $ on the left hand side means nothing - it's just a character in a variable name, but they use it as a convention to remind themselves that they're storing a jQuery selector. I'd avoid it, simply because it adds to the confusion, but it's out there, so I just wanted to mention it.
var is used to create any kind of variable. Could be var diceRoll = 4 or var myMessage = "Hello!", or anything else.
$ is a function that jQuery provides, which behaves in different ways depending on what you pass to it. For example, if you pass it a string (e.g. 'nav'), it will find every nav element in the document and return a set of jQuery objects (elements) - one for each DOM element it finds. When you say var nav = $('nav');, you are assigning this set of jQuery objects to your nav variable, so you can work with it later. So far so good.
Instead of passing a string to $, you technically could pass jQuery objects back into the $ function, which is what you are doing when you say $(nav).hide();. DOING THIS MAKES LITTLE SENSE - it will just return the same array of jQuery objects, nav, which you put into it in the first place!!
Personally, I like to prefix any variable which holds a jQuery object with a $ sign, i.e. var $nav = $('nav');. This is just a convention that allows me to see at a glance that this variable holds a jQuery object (element) rather than a native DOM element, or integer, or so on. If I ever see $($myVar) in my code, I know it's probably time for bed...
Update: there are other things that it DOES make sense to pass into the $() function, apart from strings. Passing in a DOM element, for example (such as saying $(document)) creates a jQuery object representation of that DOM element, which can be very useful.
All of these answers are pieces to the entire answer . . . let me add yet another piece. :)
As others have said, the $(...) notation is a JQuery function that returns a JQuery object. Depending on what "..." is, determines how that is done.
Some examples:
if you put a selector, such as "div", in there, you will get a JQuery object that contains all of the DOM elements that match the selector pattern . . . in this case, all of the <div> elements.
if you pass a string representation of an HTML element (e.g., "<div></div>"), you will get a JQuery object that points to a newly created <div> element.
if you put a DOM node reference in there (e.g., one created by using document.getElementsByTagName("div")), it will create a JQuery object that points to that node(s) in the reference.
The whole point of this is that JQuery works with JQuery objects, so these various functions help programmers create them.
Now this is where we get to your question . . .
Each time you use $("..."), you are creating a brand new object, so, for example the following code will produce two unique JQuery objects, each of which pointing to the identical DOM elements:
var $firstObject = $("div");
var $secondObject = $("div");
So, if you do a comparison of them (like this ($firstObject === $secondObject)), they will not be seen as equal, because they are not the same object.
Now, let me do a slight variation of your second example to add a little more clarity. If you create a third variable and set it equal to the second one, like this:
var $thirdObject = $secondObject;
. . . you have two elements that are actually pointing to the same JQuery object, so they ARE actually equal (i.e., ($secondObject === $thirdObject) will evaluate as true).
Now finally, what you've shown with this peice of code:
$(nav).hide();
. . . is simply another example of trying to create a JQuery object . . . this time using another JQuery object. Doing this with that third variable that I created above, however, will now break the relationship that it has with the second variable . . . ($secondObject === $($thirdObject)) . . . they are no longer equal, because the two sides of the comparison no longer point to the same object. Much like the comparison between $firstObject and $secondObject from earlier, that comparison is using two unique JQuery objects.
However . . .
Unlike some of the other answers, I would disagree that it is a completely incorrect form of coding . . . while I would never use it in the situation that you provide in your example, passing a JQuery object into the $(...) function is essentially the same thing as using .clone(). The two $bar assignments below are functionally equivalent:
var $foo = $("<div></div>");
var $bar = $($foo);
var $bar = $foo.clone();
The JQuery API even makes the same point (http://api.jquery.com/jQuery/):
Cloning jQuery Objects
When a jQuery object is passed to the $() function, a clone of the object is created. This new jQuery object references the same DOM elements as the initial one.
EDIT :
Out of curiosity, I set up a quick test at jsPerf and the $($foo) approach is pretty significantly faster than .clone() in Firefox, IE9, and Chrome: http://jsperf.com/clone-technique-test
var nav = $('nav');
$(nav).hide();
nav is already a jQuery object so $(nav) is useless.

Refactoring jQuery to use $(this) and add/remove classes from another element

so I have this idea I'm working on over on Codepen. I've got it working as it is but before I go and add more clickable areas I've realized a massive need to refactor and DRY things up. So far it works but it's ugly as hell and would involve a massive amount of repeated code.
So I'm trying to replace the many $(.class).click(function() { ... }); functions with a switch statement that uses $(this) to populate a single .click function instead. But I'm lost.
You can see everything here and edit it also: http://codepen.io/lukewatts/pen/ubtmI
I feel like I'm close but I've hit a wall. The top commented out part is the DRY attempt while what is uncommented for now is the working version. Click the min, off, max words or the LEDs to see it work.
Thank you very much in advance for any advise on this. PHP is my main language to be honest.
P.S. I had leds.click(function() { ... }) and I replaced it with leds.on(function() { ... }) but still nothing.
I understand what you are trying to do, but that not how the jQuery object works. In order to check for the object to match a selector, you will have to use .is().
As such, you will not be able to use a switch, but you will have to use a serie of chained ifs to achieve the goal the way you are trying, such as
if ( $this.is('.led[data-level="one"]') )
var led = $('p.min a');
var level = "one";
I have updated your CodePen example to work in this way: Codepen
As I mentioned in my comment to the question, though, I am not making any code review here, just fixing what didn't work for you. I am not sure this is actually a better approach than your messy original one, to be entirely honest.
The refactored version looks good for me. If you don't like to use addClass and removeClass you may directly change the class property of the element:
indicator.attr("class", "one on");
The reason your switch statement doesn't work is because every time you create a jQuery object, it gets an Id, so when the switch tries to compare $this to a selector like $(p.min a), they won't be equal. However, if you used multiple if statements with $.is, you could compare:
$this = $(this)
if($this.is('p.min a')) {
// do work
} else if($this.is('p.max a')) {
// do work
}
I wouldn't, however, recommend this approach. For more complex pages, I'd recommend a binding framework like Knockout.js. For something small, you're adding a lot of complexity. For clarity: If this becomes part of a larger control set or system, a binding framework would be useful. For the control as-is, both a binding framework and the OP's current approach are overkill.
You may want to look at event delegation, I find it very helpful to keeping things DRY. Clicks will bubble up the DOM tree to higher elements, and you can register your handler on an ancestral element. This is actually ideal, as you only bind a single handler to a single element, instead of binding to multiple elements and thus you realize a performance benefit in addition to cleaner code.
First thing, wrap all your .led elements in a <div id="leds">:
<div id="leds">
</div>
Now create your handler:
$('#leds').bind('click', function(e){
var target = e.target;
var $target = $(target);
//do interesting stuff
if (target.nodeName === 'A') {
var level = $target.data('level');
if(level = 'one'){
//do more interesting stuff
}
}
}
});

A jQuery plugin to do multiple things to a single jQuery object?

I find myself doing different things to the same jQuery object a lot.
So instead of doing something like this:
var thing = $("pile_o_selectors");
thing.blah;
thing.blah_2;
//...
thing.blah_n;
or even worse
$("selectors").blah;
$("selectors").blah_2;
//...
$("selectors").blah_n;
So, I made a little jQuery plugin to let me do this:
$("selectors").do(function(){
this.blah;
this.blah_2;
this.blah_n;
});
Is there a built in jQuery function that already does this? Or even a plugin that already exists and is tested and mature so I don't have to put effort into making sure mine works in all cases? I tried searching the web a bit, but I don't even know what to call it.
Not 100% sure what those 'things' you want to do are, but can they simply be chained?
http://www.w3schools.com/jquery/jquery_chaining.asp
i.e. $("#p1").css("color","red").slideUp(2000).slideDown(2000);
You can just chain them. For example:
$('selector')
.hide()
.text("Hello, world!")
.fadeIn();
This works for most methods that have nothing obvious to return; in that case, they return the jQuery object again, making it possible. However, if they need to return something, then they can't return the jQuery object, and you cannot chain any further.

Strange Javascript statement

if (1) {
google_conversion_value = 1;
}
What is the meaning of the above statement? I mean, this looks like it will always execute so why bother with the if statement?
updated: one reason might be remnants of scripting on the server side. Any other ideas?
updated2: could as easily change the value of the assignment without bothering with the if statement, no?
There are two likely explanations:
It's a leftover from debugging.
The file containing this code is generated dynamically and the original sourcecode contains something like if(<?php echo $some_stuff_enabled; ?>)
However, in the latter case it would have been cleaner to output that code block only if the condition is met - but maybe it's used in some crappy template engine that just allows replacements but no conditionals...
I've seen this before, and I've always assumed it was a remnant of some old condition that was no longer needed, but never removed. I can't see any actual reason to do something like that otherwise.
Potentially because the person writing the code wanted an easy way to turn it off and on again, this is especially useful if there is a lot of code inside the block (not the case here).
Another possibility is that the original programmer couldn't be bothered writing the logic or, more likely, it hadn't been specified so the "if" was left as a placeholder.
More than likely left in from a debug release or something similar. You're right, it will always execute. It could also have been done like this so that it can be easily enabled / disabled by setting the if to 0. Perhaps the developer intended to use it as a flag somewhere else in the code?
actually, this happens when the "if" condition is driven from server, so instead of doing the right thing and not produce the script when the condition is false, they do something like this:
if (<% if (my_server_condition) then Response.Write("1") else Response.Write("0") %>){
// code goes here
}
Perhaps the if statement used to check for a legitimate conditional, and then someone replaced it with a truthy value for testing/debugging/etc.
You're right, it will always execute because 1 is truthy. I would go through your source control history and investigate that line to see if it used to contain a real conditional. If the conditional was always 1, then it's likely a debugging statement. Otherwise someone might have meant for it to be a temporary change, and may not have meant to check that in (which could be bad).
I'm not sure where this code is from, but as you indicated it will always execute. As for why you'd do this, there are times where you want to see what the result of branch code would be, without having to setup an environment. In this case you can comment out the actual value and replace it with if(1) instead for testing:
// if( ... some hard to achieve condition )
if (1) {
// Now you can see what happens if this value is set quickly
google_conversion_value = 1;
}
Of course the problem with this is that it's sometimes easy to forget to remove the if(1) and uncomment the proper condition.
This is actually the javascript recommended by Google on http://support.google.com/adwords/bin/answer.py?hl=en&answer=1722054#nocomments (click on Step 2 for the sample HTML)

Dojo marginBox return different value

Anyone can guide me what's the difference between
this.marginBox
and
dojo.marginBox(this.node)
I'm confusing with this two where they return different value.
What are the two values you're getting back? (I haven't used dojo for a while, but I seem to remember one of them including padding and the other not?)
Dojo only provides a dojo.marginBox() method — I am not aware of Dojo providing any kind of prototype or mixin that enables a this.marginBox method. In other words, only dojo.marginBox(this.node) is correct.
It would have helped if you provided examples of what those methods are returning for you.
I would expect:
var example = this.marginBox;
to return undefined in most circumstances. However if you have tried to assign to this.marginBox like this:
// Don't do this - marginBox is not a DOM property!
this.marginBox = 10;
then future calls to this.marginBox would return 10... it might look like it is doing something, but it's got nothing to do with Dojo or CSS and will just return what you put in... not very useful!
I would be very careful in using dojo.marginBox, I was browsing around an issue about it and I found the following:
https://bugs.dojotoolkit.org/ticket/12492
unfortunately the dojo team won't fix the problem because the method dojo.marginBox(..) will not work for hidden nodes, quoting the ticket "the behavior is undefined when called on hidden nodes".
What I did I checked the node's clientWidth / Height.

Categories

Resources