Control references in jQuery - javascript

function eegetdropdownvalue_str(ctl){return ctl.selectedIndex>=0&&ctl[ctl.selectedIndex]?ctl[ctl.selectedIndex].value:''}
The above function is called with
co.p1A10=eegetdropdownvalue_str(document.formc.p1A10);
I want to switch the call over to jQuery to drop the document.form reference however doing this
co.p1A10=eegetdropdownvalue_str($('p1A10'));
Does not reference the control correctly - How should I do this?

There's two things wrong with your code.
First, $('p1A10') references nothing.
jQuery selectors work almost identically (if not completely identically) to the way css works.
So, just ask yourself how you would reference the object(s) in question in CSS and you're half way there.
I'm assuming that p1A10 is the name or id of an object. Since we're using CSS/jQuery syntax, this should be an id, although you can select by other attributes such as $("select[name='p1A10']") .
To reference an object by ID we use the # character (again, just like in CSS). So we can select your node via $('#p1A10').
The second problem is that your function is expecting a DOM object not a jQuery object. To keep your code intact, we need to say $('#p1A10')[0] where 0 is the first element within the collection of jQuery elements.
I've provided two examples to explain this a little better. One uses your existing infrastructure and one replaces it.
http://jsfiddle.net/TD6Uu/5/
Hope it helps.

Given a form with id formc and a select with name p1A10 you could e.g. use:
o.p1A10 = eegetdropdownvalue_str($('#formc select[name="p1A10"]').get(0));
If this doesn't do it, please provide use with the exact HTML structure

Related

Should I add an 'if' statement to jQuery that doesn't execute on certain pages?

I like to keep my code clean as possible and I am just wondering what would be the best way to go around this problem when it comes to best practices.
I have the following function:
$('.car-hub-header-help, #assistance-overlay').click(function(){
$('#new-car-hub, #new-car-offer').toggleClass('assistance-active');
$('#pulman-assistance').toggleClass('pulman-assistance-active').css("top", fixedPositionCalculator);
$('#assistance-overlay').toggleClass('assistance-overlay-active');
$('#new-car').toggleClass('assistance-active-body');
$('#new-car-offer-cta').toggleClass('assistance-active-cta');
});
Now as you can see this function is very simple it just toggles classes based on a click event. One issue that I am having is that the element new-car-offer-cta is only on specific pages and it seems like this is bad practice to run that part of the function if the element isn't on some of my pages.
So I am just wondering if this would be better practice:
$('.car-hub-header-help, #assistance-overlay').click(function(){
$('#new-car-hub, #new-car-offer').toggleClass('assistance-active');
$('#pulman-assistance').toggleClass('pulman-assistance-active').css("top", fixedPositionCalculator);
$('#assistance-overlay').toggleClass('assistance-overlay-active');
$('#new-car').toggleClass('assistance-active-body');
var carOfferCta = $('#new-car-offer-cta');
if (carOfferCta.length) {
carOfferCta.toggleClass('assistance-active-cta');
};
});
So that part of the function wont run unless the element is on the page. I am just wondering what is classed as the best practice. Thanks
I would advise against doing the check at all. The beauty of jQuery is that you usually don't have to know whether your selector selects 0, 1 or more elements, the methods will just work (even if working is doing nothing at all).
If you start adding these checks everywhere, you're just coupling different parts of your logic more tightly together.
(That's also why I usually prefer not to use id selectors, but select based on classes instead. If then your html changes and e.g. your jQuery code needs to act on more elements, you don't need to change anything in the structure of your page, just apply the right classes.)
jQuery already does that check for you, if the selector inside $() doesn't match any elements, the functions you chain to it won't do anything (not even produce an error). So there's really no need to check explicitly. With these exceptions:
if you want it to be absolutely obvious to anybody reading your code, that the element you're trying to create won't exist on every page that uses your script or
if you want to do a bunch of different things in your if statement,
then it makes sense to explicitly write if ($element.length).
It's better to ask if the element's val is !=undefined, rather than asking for it's length, since that way you're assuming it does exist on the page. You can add the length check right after asking for the element's existence, I usually do as follows:
if($('#new-car-offer-cta').val() != undefined && $('#new-car-offer').val().length > 0){
//do something
}

Why specify [0] when using new FormData()?

I've just spent a good few minutes debugging why new FormData($("#ImageEditorForm")); isn't working. After turning to Stack Overflow, I found a suggestion in another thread to use new FormData($("#ImageEditorForm")[0]); instead.
I made the change, not expecting anything to happen. Instead, the code now works perfectly and as expected. Previously, nothing was being submitted to the server. Now, form data and files appear as expected.
My question is why is the "[0]" required? There is only one element with that ID in the DOM. Selecting by ID should surely return only one element? What is going on here?
$("#ImageEditorForm") returns a jQuery object and FormData requires a DOM Node.
You can use document.getElementById(id); which returns a DOM Node.
FormData(document.getElementById("ImageEditorForm"));
Or use document.querySelector(selector); which takes a css selector and returns the node if found and null otherwise.
When selecting with jQuery, the returned object is a jQuery object, and to get the actual DOM-node this represents, you use [0] on the jQuery object.
If you had used a selector which returned a couple of results, it would be easier to understand why you would need to index into the object to get to the actual DOM-node, but this is standard jQuery.
And as andlrc said, you need to pass an actual DOM-node to the FormData function.

How to get the k-th element in a jQuery set ... AS A JQUERY ELEMENT

So I encounter this situation often and I want to figure out a better way of going about it. I using the naming convention prefixing my jQuery elements with $ so that I can distinguish them from DOM elements. For example, the following:
$pointers = $('#pointer-box div.pointer');
The problem with that is, if I want to get the 3rd in the result as a jQuery, I have to do
$($pointers[2])
which looks awkward. Unless there's a better way of doing this?
You can use .eq() jQuery method
$pointers = $('#pointer-box div.pointer');
var element=$pointers.eq(2);
Given a jQuery object that represents a set of DOM elements, the .eq()
method constructs a new jQuery object from one element within that
set. The supplied index identifies the position of this element in the
set.

Why no error when accessing a DOM element that doesn't exist?

I have some divs with partial views in them. Why would a reference to a div that doesn't exist not show some kind of error? For example, I only have one taskN div right now:
<div id="task1">
#Html.Partial("~/Views/PartialViews/TaskDosCommand.cshtml")
</div>
This is my jQuery to show the div:
$('#task' + task.PrestoTaskType).show();
When task.PrestoTaskType is 1, the task1 div correctly displays. However, when task.PrestoTaskType is anything but 1, like 2, then nothing displays (which is good), but there is no error; no error shows on the web page, and nothing displays in the Chrome developer tools console:
Shouldn't some kind of error display when accessing a DOM element that doesn't exist?
No, because what jQuery does is .show() all elements that the jQuery object wraps. If that's no elements at all, then so be it.
That's precisely a monad-like aspect of jQuery that makes it so useful: imagine the code you 'd have to write if things didn't work that way:
var $whatever = $(...);
if ($whatever.length) $.doSomething();
This is simply worse: you need to introduce a variable (in order to avoid waste) and a conditional... for what gain exactly?
If you want to see what jQuery matched you can do that very easily with .length as above, perhaps also using .filter in the process.
One of the nice things about jQuery is that all jQuery elements return a collection, whether that is 0, 1, or many elements. This is convenient because you don't need to check the size of the collection or wrap it in an array yourself when you want to call methods on it (each for example doesn't break for 0-1 elements).
While what you're talking about is frustrating in this particular case, it is better for jQuery to work this way so you don't have to do those sorts of checks everywhere else.
If you want to branch code based on the existence of such an element, you can do this:
var task = $('#task' + task.PrestoTaskType);
if (task[0]) {
task.show();
} else {
// task not found
// take appropriate steps
}
The [0] accessor will return the first DOM element in the jQuery object or undefined if the jQuery object is empty. Since your jQuery object was constructed with an ID selector, it either contains exactly one DOM element or it's empty.

Hiding multiple tag with same name or class

I have using prototype 1.5. Can you please tell me, how can i hide/show the div tag with same name or class.
Element.hide('indicate')
But, the above line only satisfy to hide the first element only. "indicate" is the id.
As pointed out, the $$ function is required. It returns an array so you need to invoke hide on all items.
$$('.indicate').invoke('hide');
Or, for bonus showing off points, you can use the function directly as an object:
var hideFunc = Element.hide;
$$('.indicate').each(hideFunc);
The advantage of this technique means you can easily swap the function for another, such as a Scriptaculous effect.
hideFunc = Effect.SwitchOff;
Having the same id for two elements isn't supported in HTML, so there's no methods in Javascript to handle it. No matter what framework you're using.
Prototype provides the $$() function which you can use to query any CSS selector.
So if you have multiple items with a single class, you can query them like this:
$$('.indicate');
See the Prototype manual: http://www.prototypejs.org/api/utility/dollar-dollar
By the way, since you're using Prototype 1.5, I could also mention that it gives you a .getElementsByClassName() function as well. However, this has now been deprecated in more recent versions since its functionality is already covered by $$(), and to avoid confusion, since modern browsers implement a native function with the same name, but different syntax.
So don't use it, but for the sake of completeness, here is the manual link: http://www.prototypejs.org/api/element/getElementsByClassName
ID's have to be unique. Select with a class instead.
$$('div.indicate').hide();
or with its name attribute
$$('div[name=indicate]').hide();

Categories