Identity selectors in jQuery returning arrays - javascript

Suppose I have a div tag like this:
<div id="group-dialog" class="modal-dialog">
Now I want to grab it as a jQuery object (in this case so I can run .dialog()).
When I try this:
var gDialog = $('#group-dialog');
I get an array back (!!).
Why am I getting an array? Isn't the point of having an ID attribute that there's only one? I can see getting multiple p's or .my-css-thing back ...
Next question:
I have this array with 1 object in it that I now want to access as a jQuery object.
When I do this:
$(gDialog[0])
And pull it up in F12, I still have an array!! I thought I de-referenced the array already by picking the first element.
This doesn't seem to help either:
var gDialog = $('#group-dialog:first');
This is basic, but I run into this problem a lot. It seems like it used to be a lot simpler!
What is the best way to access this DOM element as a jQuery object?

Answer 1
jQuery selectors always return arrays.
Selection with id attribute is a particular use case and ideally the result should be unique. However, there is nothing preventing you from having duplicated ids in a HTML document (although this is bad practice).
Answer 2
The following code will get you the first element as a DOM object:
var gDialog = $('#group-dialog')[0];
Note: you may want to check the size of the return array first.
As far as I know, there is no way to transform this DOM element back to a jQuery object. The standard use case would be to directly used $('#group-dialog') and asume that it is found and unique.

Try using .get(). Though I'm not sure it will work with dialog()
Retrieve the DOM elements matched by the jQuery object.
var gDialog = $('#group-dialog').get();
If you're trying to grab it to use it on a dialog, you can just put
$(document).ready(function(){
$('#group-dialog').dialog({put options here})
});

Related

Looping through selected checkboxes jQuery

I'm trying to get the values of all selected checkboxes with the following code to insert them in a textarea.
$('input[name="user"]:checked').each(function(){
parent.setSelectedGroup($(this).val()+ "\n");
});
but i always get only one value.
How to write the code in a correct way to get the value of ALL selected checkboxes?
Thanks ahead!
EDIT
1) "parent" because the checkboxes are in a fancybox.iframe.
2) setSelectedGroup in the parent window is
function setSelectedGroup(groupText){
$('#users').val(groupText);
You are getting all the values, simply on each loop through the collection you're passing a new value to setSelectedGroup. I assume that method replaces content rather than appending so you are simply not seeing it happen because its too fast.
parent.setSelectedGroup(
//select elements as a jquery matching set
$('[name="user"]:checked')
//get the value of each one and return as an array wrapped in jquery
//the signature of `.map` is callback( (index in the matching set), item)
.map(function(idx, el){ return $(el).val() })
//We're done with jquery, we just want a simple array so remove the jquery wrapper
.toArray()
//so that we can join all the elements in the array around a new line
.join('\n')
);
should do it.
A few other notes:
There's no reason to specify an input selector and a name attribute, usually name attributes are only used with the input/select/textarea series of elements.
I would also avoid writing to the DOM inside of a loop. Besides it being better technique to modify state fewer times, it tends to be worse for performance as the browser will have to do layout calculations on each pass through the loop.
I strongly recommend almost always selecting the parent element for the parts of the page that you're concerned with. And passing it through as the context parameter for jquery selectors. This will help you scope your html changes and not accidentally modify things in other parts of the page.

Getting all HTML elements in the DOM where an attribute name starts with some-string

I've stumbled upon a tricky one, that I haven't been able to find any references to (except one here on Stackoverflow, that was written quite inefficiently in Plain Old Javascript - where I would like it written in jQuery).
Problem
I need to retrieve all child-elements where the attribute-name (note: not the attribute-value) starts with a given string.
So if I have:
<a data-prefix-age="22">22</a>
<a data-prefix-weight="82">82</a>
meh
My query would return a collection of two elements, which would be the first two with the data-prefix--prefix
Any ideas on how to write up this query?
I was going for something like:
$(document).find("[data-prefix-*]")
But of course that is not valid
Hopefully one of you has a more keen eye on how to resolve this.
Solution
(See accepted code example below)
There is apparently no direct way to query on partial attribute names. What you should do instead (this is just one possible solution) is
select the smallest possible collection of elements you can
iterate over them
and then for each element iterate over the attributes of the element
When you find a hit, add it to a collection
then leave the loop and move on to the next element to be checked.
You should end up with an array containing the elements you need.
Hope it helps :)
Perhaps this will do the trick -
// retrieve all elements within the `#form_id` container
var $formElements = $("form#form_id > *");
var selectedElements = [];
// iterate over each element
$formElements.each(function(index,elem){
// store the JavaScript "attributes" property
var elementAttr = $(this)[0].attributes;
// iterate over each attribute
$(elementAttr).each(function(attIndex,attr){
// check the "nodeName" for the data prefix
if (attr.nodeName.search('data-.*') !== -1){
// we have found a matching element!
if (selectedElements.length < 2){
selectedElements.push(elem);
break;
}else{
if (selectedElements.length == 2){
break(2);
}
}
}
});
});
selectedElements will now hold the first two matching elements.
jsFiddle
You can use jquerys filter() method to have a selections elements being processed by a function. Inside that function you are free to do whatever you want to.
So start with selecting all elements inside the dom tree and filter out everything you dislike. Not especially fast, but working.

getElementById and JQuery not returning same result

I'm not getting the same result when I use JQuery vs javascript functions.
This is the HTML
<form id="testform">
<div id="FormContainerID"></div>
<input type="button" id="y" value="Button" />
<div id="ListContainerID"></div>
</form>
Here is the Javascript
01 var Form = document.getElementById('y').form;
02 //var Form = $('#y').closest('form');
03 alert(Form);
When Activating row 1, I get a legal form object. The Alert says "object HTMLFormElement" and everything works fine.
But if I use row 02 instead, Alert says "object Object" and then I ofcourse get errors becaus it isn't a real Form object.
Why is JQuery not returning the correct Object?
I get the same result with Chrome and IE8.
[EDIT]
I'm using JQuery version: jquery-1.5.1.min
[SOLUTION]
Thank you for clearing this up. I Changed the code to:
var Form = $('#'+fChildID).closest('form')[0];
...and now it works as a charm.
Vivek Goel was the first to answer, so creds to him. I voted up you other guys that explained the JQuery instance model.
Thank you.
jQuery returns a jQuery instance when you use it to look things up, not the raw DOM element. The jQuery instance is a wrapper around the set of matched elements, and allows you to apply set-based operations to the elements. This is one of the absolute fundamentals of using jQuery.
You can also access the raw elements if you like using array-like notation — [0], [1], etc., up to .length - 1. So in your case, since you're getting just one element, it would be Form[0]. If your code matched multiple form elements, it would be Form[1] for the second one, Form[2] for the third one, etc. (Using the [] notation is surprisingly hard to find in the documentation, though, one of the gaps in my view; in the old days you used the get method, but you only need that now if you're using its special handling for negative indexes.)
You frequently don't need to access the raw elements at all. You haven't said what you're going to do with the form once you have it, but if you were to (say) submit it, just call the submit function on the jQuery instance, and it will submit the form. If you wanted to get an attribute from it, there's the attr jQuery function (so for instance, val = Form.attr("action")).
jQuery is very set-based, but it's assymetrical, which feels weird at first but works fairly well in practice. When getting a value, functions usually get the value from the first matched element only. When setting a value, functions usually set it on all the matched elements.
This is because the jquery statement is returning a jquery object and not a form object.
You need something like Form[0] to access the form element.
with jquery use
alert(Form[0]);
http://jsfiddle.net/dvCtr/
Try
var form = $("#y").parent
this should return the parent of yin the DOM tree

How can I call an element from an array created by "document.getElementBytag()"?

I am trying to make a page work for my website using the mootools framework. I have looked everywhere I can think of for answers as to why this isn't working, but have come up empty.
I want to populate several arrays with different data types from the html, and then, by calling elements from each array by index number, dynamically link and control those elements within functions. I was testing the simple snippet of code below in mootools jsfiddle utility. Trying to call an element from array "region" directly returns "undefined" and trying to return the index number of an element returns the null value of "-1".
I cannot get useful data out of this array. I can think of three possible reasons why, but cannot figure out how to identify what is really happening here:
1. Perhaps this array is not being populated with any data at all.
2. Perhaps it is being populated, but I am misunderstanding what sort of data is gotten by "document.getElementBytag()" and therefore, the data cannot be displayed with the "document.writeln()" statement. (Or am I forced to slavishly create all my arrays?)
3. Perhaps the problem is that an array created in this way is not indexed. (Or is there something I could do to index this array?)
html:
<div>Florida Virginia</div>
<div>California Nevada</div>
<div>Ohio Indiana</div>
<div>New York Massachussetts</div>
<div>Oregon Washington</div>
js:
var region = $$('div');
document.writeln(region[2]);
document.writeln(region.indexOf('Ohio Indiana'));
Thanks for helping a js newbie figure out what is going on in the guts of this array.
$$ will return a list of DOM elements. If you are only interested in the text of those DOM nodes, then extract that bit out first. As #Dimitar pointed out in the comments, calling get on an object of Elements will return an array possibly by iterating over each element in the collection and getting the property in question.
var region = $$('div').get('text');
console.log(region[2]); // Ohio Indiana
console.log(region.indexOf('Ohio Indiana')); // 2
Also use, console.log instead of document.writeln or document.write, reason being that calling this function will clear the entire document and replace it with whatever string was passed in.
See an example.

How to get object values and properties in jquery?

I am using jQuery selector to get the values of all CMS components on the page using $('div.cmscomponent') but how can I test this to see if am actually getting the list of compoents on the page.
I use:
var temp = $('div.cmscomponent');
alert(temp);
and result that I get is [object OBJECT] and so how can I test this ? and how can I get values of the object and its properties.
$() returns a jQuery wrapper object, whose contents is usually a list of DOM elements, along with properties and methods that apply to those elements.
If you want to get an element, you can access them using array-style indexes or the get() method:
alert(temp[0].tagName); // Fetch the first element, alert the `tagName`
alert(temp.get(1).tagName); // Fetch second element, alert the tagName
To check to see how many elements the result contains, you can use .length, just like you would on an array or collection/nodelist:
alert(temp.length); // Alerts number of elements found.
Here is a javascrip include that will enable you to view object structure and information.
EX: dump(temp, true);
http://www.netgrow.com.au/files/javascript_dump.cfm
Well it depends on what you want to know about the matched objects. Some examples:
var temp = $('div.cmscomponent');
alert(temp.length); // number of matched elements
// Alert each id attribute of every matched element
$(temp).each(function(index) {
alert(index + ': ' + $(this).attr("id"));
});
var temp = $('div.cmscomponent').length;
alert(temp);
If by "how can I test this", you meant "how can I write a unit test for this?", the answer is that you shouldn't. You didn't write jQuery, so you should assume it's already been unit-tested. (If there were a problem with jQuery, though, you can write integration tests would catch this.)
On the other hand, if you meant "how can I sanity-check what jQuery is telling me to make sure I didn't goof on the inputs?", there are a few ways:
Check that .length matches the expected number of items.
Check that an XPath query for the same nodes ("//div[#class='cmscomponent']") returns the same number of values.
Check that the content of the Nth node matches what you expect.
Otherwise, it's probably best to use a third-party tool like Firebug.
If all you want to do is test if your code is doing what you expect, Firebug is your friend here. It will give you a console to type a command like $('div.cmscomponent') and then interactively explore the results that are returned by it.
You can then mouseover each item that your command returned and it will be highlighted on the page, so you can see which item the command returned, and if those items are the ones you expected/wanted.

Categories