Looping through selected checkboxes jQuery - javascript

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.

Related

Use parentElement multiple times

I'm editing a plugin that creates filters on an table like excel(drop-down), the problem is when I use it on a table that uses a table inside it, in fact the plugin will also take the values ​​of the sub-table.
I therefore decided to exclude from the initial array, made up of all the rows, those elements that have a parent with a table that does not have an id.
So i forEach array and see if have id like:
this.tds.forEach((el) =>{
console.log(el.parentElement.parentElement.parentElement.id);
});
I was wondering if using parentElement three times like this is correct or there is another way
It's perfectly fine, as long as you're sure that the structure will always be the same.
But let's assume that you don't know if the structure will always be like this, but you do know the class of the parent you're looking for (or any other CSS query), then you could use the Element.closest() method to query your way up.
So let's say you want to find the closest table with an id value.
this.tds.forEach((el) => {
const parent = el.closest('table:not([id=""])');
if (parent !== null) {
console.log(parent.id);
}
});
This will walk up the DOM tree from the el as starting point, doing something in the likes of parentElement.parentElement.parentElement... until it reaches an element that has a value in the id attribute.
There's nothing wrong with the code.
But if you want to make the code a little more robust you can use Optional Chaining.
this.tds.forEach((el) =>{
console.log(el?.parentElement?.parentElement?.parentElement?.id);
});

How to query on object type in dojo?

We can use dojo.query to get certain elements based of CSS selectors but how do we query on object types?
For example, get all the TextBox elements on the page and then use dojo.connect to bind a function?
This is not completely supported, yet there are two ways of doing it as i see it.
One, figure out which is the unique class for a TextBox (.dijitTextBox), call dojo.query('.dijitTextBox'), loop result dojo.forEach and get the widget with dijit.getEnclosingWidget(domnode)
var textboxArray = [];
dojo.forEach(dojo.query('.dijitTextBox'), function(domnode) {
textboxArray.push(dijit.getEnclosingWidget(domnode));
});
Or two, loop the dijit.registry._hash, test declaredClass, if its dijit.form.TextBox - connect.
var textboxArray = dojo.filter(dijit.registry._hash, function(widget) {
return widget.declaredClass && widget.declaredClass == 'dijit.form.TextBox';
})
Depending your setup, choose the most efficient one. The latter is commonly best - unless you have 100's of widgets in your page. The first will have to xpath all your elements of the page. Allthough, remember that dojo.query takes a second parameter as 'parentNode'

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.

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.

JQuery Add two selections together

With the power of jquery...
I'm attempting to add two selections together, they both contain the same type of element (<option>).
But the add(..) method doesn't seem to be playing ball.
var matchingRemovedOptions = removedOptions.filter(function() {
return this.text.toLowerCase().match(str.toLowerCase());
});
tempOptions.add(matchingRemovedOptions);
console.log(tempOptions.length);
console.log(matchingRemovedOptions.length);
As you can see im trying to filter out some option elements from the removedOptions selection and add these to the tempOptions selection.
But when using the console.log, the length of tempOptions stays the same as in, does not increase.
.add() returns a set with the elements/selector added, it doesn't actually add them to the set that it's called on. To get the effect you want, you need to update to the set it returns, like this:
tempOptions = tempOptions.add(matchingRemovedOptions);
If you think about all other tree traversal functions, they behave the same way, for example obj.find("...") doesn't change obj to what's found, only the rest of the chain operates on that set, which .find() returns.
You need to do another assignation:
tempOptions = tempOptions.add(matchingRemovedOptions);

Categories