How can I rewrite jQuery without guard clause? - javascript

How can I rewrite this jQuery to be more terse and without the guard clause?
var myTextBox = $('#myTextBox');
if (myTextBox )
myTextBox.val("");
The guard clause is there simply to ensure that the element exists on the page before trying to set it's value but the code seems bloated and most of it unnecessary.
What's the preferred solution to this?

$('#myTextBox').val("") will do nothing if the jQuery object has a length of 0, so simply use it.

Unless you need to cache the selector for future operations, I would do this:
$('#myTextBox').val("")
If there are none selected, nothing will get enumerated, so jQuery will not run the val() routine.

It'll work just as $('#myTextBox').val("");, if it finds no object then it will just be an empty jQuery object and the .val() routine will do nothing.

I believe that if #mytextbox doesn't exist, mytextbox will not be undefined anyway, it will be an empty jQuery object. So the check is redundant.
I also think that if you perform an operation on an empty jQuery object nothing will happen anyway, so you're safe.

Related

How do I check an element is exists in JQuery?

I have to set a specific value to an element if the element is exists.
var a = jQuery("#abc");
if(a) {
a.val("something");
}
For this, I've to check a.length to check the element is exits.
What happen if I directly set the value without checking the element is present or not?
Because, If I do the following
jQuery("#abc").val("dfd");
I don't get any error in chrome when the element is not present. So, can I continue to use like this?
or
any workaround?
Help appreciated!
What happen if I directly set the value without checking the element is present or not?
Nothing. Calling jQuery methods on an empty jQuery object (set) doesn't cause a problem, it just does nothing. This is one of the great things about the set-based concept used in jQuery. The equivalent DOM code (document.getElementById("abc").value = "something";) would throw an error, but the jQuery version doesn't.
Specifically, if the jQuery set is empty:
Calling setter methods (like your val call) becomes a no-op.
Calling getter methods — for instance, var x = $("#foo").val(); — returns the value undefined.
Calling traversal methods — for instance, var divs = $("#foo).find("div"); — gives you a new empty set.
You only need to check (using if (a.length) as you said, or if (a[0])) if you actually care.
jQuery("#abc").val("dfd");
I don't get any error in chrome when the element is not present. So, can I continue to use like this?
Yup.
jQuery's val() method simply sets (or gets) the value of each matching element. If there are no matching element, there will be no value to set (or get). You don't need to check if the element exists first.
From jQuery's val() documentation:
Description: Set the value of each element in the set of matched elements.
If there are no matched elements, nothing will happen.
Try with -
jQuery("#abc").length > 0
Yes, you can safely continue. JQuery just executes a function on all elements found by the selector - if there are none, it does nothing. There's no error.

Do you need to check if a jQuery object exists?

Let's say you have a website of 100 pages and there is a div with an id of #unique-div that only appears in page-5.html, but not in the other 99 pages and to be extra simple with the example you have a JS file that is loaded on all pages, and inside it there is this:
var uniqueDiv = $('#unique-div');
uniqueDiv.addClass('random-class');
does that have any negative impact in any possible way (for instance, performance)? Would it better to do a length check first?
var uniqueDiv = $('#unique-div');
if ( uniqueDiv.length ) {
uniqueDiv.addClass('random-class');
}
If so, why?
Or what about if you are chaining objects like this:
var uniqueDiv = $('#unique-div');
someVar.add(moreVars).add(uniqueDiv).addClass('random-class');
If the object doesn't exist, what happens?
I tried looking this up, but I have always wondered this.
It is the responsibility of ANY jQuery method to have a "proper" behavior whether there are 0, 1 or more than 1 DOM objects in the current jQuery object that they are called on. So, as long as you aren't using some broken jQuery plug-in methods, you do not have to test the length before calling a method and this includes situations where you are using chaining.
So, in your case this would be perfectly fine, even if you had no idea whether #unique-div actually existed:
$('#unique-div').addClass('random-class');
If the div didn't exist, then the .addClass() method would just do nothing.
Note: that some methods that retrieve a value such as .val() are coded to only operate on the first DOM element in a jQuery object and you will have to check with an individual method like that what they are coded to return if there are no DOM objects in the jQuery object. For example, .val() will return undefined when there are no DOM objects in the jQuery object.
There might be some infinitesimal amount of performance saving, but it's really negligible. There are probably going to be plenty of times in your code you'll do a for-loop through an array, acknowledging the length might be zero.
JQuery objects always have some size to them, and all methods I know of (ie, addClass) are equipped for empty sets, so I don't see any issue with skipping the length check.

Strange ie behaviour with jquery inArray

Hello this seems to be working on IE8 :
var clsName = link.parents("div.fixed_column").attr("class").split(" ");
if($.inArray("column_one", clsName)
While this one reports error (Object expected errror in jquery).
var clsName = link.parents("div.fixed_column").attr("class");
What is the right way to do this? I thought purpose of inArray was that jquery will handle cross browser issues.
Unfortunately, this is indirectly answering your question, but... You seem to be looking to detect if an element has a class, and since you're already using jQuery, just use the hasClass method - http://api.jquery.com/hasClass/
For your specific code, try:
if (link.parents("div.fixed_column").hasClass("column_one")) {
// It has the "column_one" class
}
The more immediate answer to your question is that link.parents("div.fixed_column").attr("class") returns a single string. When the jQuery selector (div.fixed_column) returns multiple elements, which is very possible when using classes, using jQuery methods that get information (like .attr, using one parameter...to "get" the value) return the first matched element's value only.
So say the selector matches 3 elements:
["<div id='div30' class='fixed_column div30_class'></div>",
"<div id='div2' class='fixed_column div2_class'></div>",
"<div id='div17' class='fixed_column div17_class'></div>"]
Then the value returned from .attr("class") will be: fixed_column div30_class because it's the first matched element.
I'm not sure, but I think you're expecting jQuery to return an array of all the matched elements' values, which it just doesn't. So that doesn't mean jQuery isn't handling cross-browser issues, it just means you need to look up what the method does/returns.
I could've sworn that jQuery 2.0 has options for doing what you want - directly from calling the getters (or something similar), but I can't find it anymore :( Maybe I'm remembering incorrectly. Anyways, you could easily use $.each and/or $.map to look at every matched element, but it depends on what you were really trying to do with it.
You can't read the attributes of multiple elements into an array with .attr("class"). But why don't you just target the desired class in the selector like this?
var cols = link.parents("div.fixed_column.column_one");
Then change your conditional to check for an empty set:
if(cols.length) { ...

Why does jQuery.val() behave differently to the rest of jQuery

Typically in a case where jQuery fails to find matching elements using its selector the default value is never an exception but rather a lack of action.
My understanding is this is done by design to ensure that the lack of an element does not result in an error condition. However I have found that jQuery.val() does not exhibit this same behaviour. If a selected element does not exist jQuery.val() will return undefined rather than an empty string (which in keeping with the remainder of the framework I would have expected).
So why is jQuery.val() an exception to the rest of the framework and what would be the best way to change this behaviour?
The key here is chainability of jQuery methods. A jQuery method doesn't return undefined when a selector doesn't match anything because it would break the chain. Consider:
$( '#doesntExist' ).addClass( 'foo' ).fadeIn();
If the selector that doesn't match anything would return undefined it would break the chain since undefined doesn't have any methods of its own. Now every method is executed (and do nothing) whether or not the element is found.
.val() on the other hand is different since it's purpose is to return the value of an element. It doesn't chain at all unlike many other jQuery methods, because a method has to return a jQuery object for it to be able to chain. For example, $( '#foo' ).val().addClass( 'bar' ) does not work regardless of whether the element #foo exists or not.
In this light having .val() return an empty string would not make it any more in line with chainable methods, since no other method returns an empty string when the element isn't found either, and returning undefined does not break chainability since the method doesn't chain in the first place.
(By the way, the same is true for every method that returns a value, like .css() and .data().)
Usually it's more useful to know whether the value of an element is empty or whether the element doesn't exist at all, but if you prefer to always get a string back you can add a method of your own:
$.fn.stringVal = function() {
return( this.val() || '' );
};
If I use .val() to get the value of an item, I expect that item to exist. If it does not, I need to know that. Returning undefined in this case seems the best way.
As pointed out by #Ricardo, .val() performs differently in other cases as well, depending on the input.
jQuery.val() returns the value of an input (or the selected option of a "select")

A few questions about JavaScript basics - $, "is not a function"

Being fully self-taught without actually reading up on JavaScript (It's my job now, believe it or not) there are a few things I accept but don't understand.
The first one is the dollar sign.
As far as I use understand it, it's a shortcut to document.getElementById(),
but if I log $ and document.getElementById() to console - Only $ returns a value. This value however is always function(), shouldn't it be. The element? What gives?
The second issue I have is something that keeps coming up in my code and I go out of my way to change the code to eliminate it. It's the "... is not a function" error.
For example:
if ($.inArray($(div_id).val(), arr) >= 0);
Will give the error .val() is not a function. Why? And how do I use the value of div_id to see if it's in array?
Hiya. When you're using Jquery (which I assume you are), then $ will return the jquery object. This can contain an array of matched HTML elements depending on the selector you used. For example $("#foo") will return the jquery object containing the element with id foo. You can get the actual HTML DOM element out using $("#foo")[0] - using the array-style notation.
Can you give us some more info on what you're trying to achieve with the $.inArray example?
$ is a valid variable name.
So if you try to use $ without setting it, it will not work.
A lot of people/frameworks however use $ as a shortcut to document.getElementById, they would declare it at the top of the script as:
function $(id) { return document.getElementById(id); }
$ and document.getElementById is not one of the same thing. $ gives you a function in console only when you are using some library like jquery which mapes $ to a function.
.val id primarly used to get value of the form elements and that is a jquery function. I think you need to learn more around javascript and jQuery
Neither Javascript nor the DOM define $, which (as other answerers said) is often defined in general-purpose DOM libraries like jQuery, Prototype or Mootools. Based on the particular code you included, I suspect you've been coding against the jQuery API (because you use $.inArray, see http://api.jquery.com/jQuery.inArray/; though your claim that $ aliases document.getElementById confuses matters, as jQuery expects CSS selectors rather than element IDs).
When $ is expected but undefined, that usually means you'll need to include the library whose API you're using in the HTML document.

Categories