Getting array of values from jQuery object - javascript

I have following object:
$("input:checkbox:checked")
[
<input class=​"li_checker" type=​"checkbox" category_uid=​"1.3" category_language=​"da">​,
<input class=​"li_checker" type=​"checkbox" category_uid=​"1.3.1" category_language=​"da">​
]
If there is any helper in jQuery which allows me to get value of "category_uid" for all elements and returns it as the another array? Expected result:
["1.3", "1.3.1"]

Use map():
var myArray = $("input:checkbox:checked").map(function(){
return this.getAttribute("category_uid");
}).get();

As bpierre suggested, use .map(). His answer is correct.
If you need this behavior for different attributes, you might as well write is as a reusable function (“jQuery plugin”):
jQuery.fn.pluck = function(attr) {
return this.map(function() {
return this.getAttribute(attr);
}).get();
};
$('input:checkbox:checked').pluck('category_uid'); // ["1.3", "1.3.1"]
P.S. category_uid is not a valid attribute in HTML. Consider using custom data-* attributes instead, e.g. data-category-uid="foo".

Just for the fun of it, a third way, this one using attr:
var categories = [];
$("input:checkbox:checked").attr("category_uid", function(index, value) {
categories.push(value);
});
Live example
Off-topic: If you want to have arbitrary, custom attributes on HTML elements, recommend using the data- prefix defined by HTML5 (details). You can use it now, even if you're not using the HTML5 doctype (this is one of the places where HTML5 is just codifying — and reining in — current practice), and it future-proofs a bit.

var myarray=[];
$("input:checkbox:checked").each(function () {
myarray.push($(this).attr('category_uid'));
});
Live Demo

Something like
var checked_cats = new Array();
$("input:checkbox:checked").each(function() {
checked_cats.push($(this).attr('category_uid'));
});
(not tested)
p.s. saw your tweet.

Here's a more "pluginy" way to do this:
(function($){
$.fn.getAttributes = function(attribute){
var result = [];
$(this).each(function(){
var a = $(this).attr(attribute);
if(a)
result.push(a);
});
return result;
}
})(jQuery);
and then use it as follows :
var result = $("input:checkbox:checked").getAttributes("category_uid");
Haven't tested it, but it should work just fine.

Related

Use Lodash to find the indexOf a JSON array inside of an [] array

I have an array that looks something like this.
Users : {
0 : { BidderBadge: "somestuff", Bidders: 6, }
1 : { BidderBadge: "somemorestuff", Bidders: 7,}
}
I want to search the array using lodash to find a value inside of each of the user objects.
Specifically, I want to use values from another similar array of objects to find the value.
var bidArray = [];
_.each(this.vue.AllUsers, function(user) {
_.each(this.vue.Bids, function(bid) {
if(user.BidderBadge == bid.Badge) {
bidArray.push(user);
}
});
});
This is what I have and it works, but I want to do it using only one loop instead of two. I want to use something like _.indexOf. Is that possible?
If you want to avoid nesting, you just have to modify Azamantes' solution a bit
var bidders = this.vue.Bids.reduce(function(acc, bid) {
return acc[bid.BidderBadge] = true;
}, {});
var bidArray = this.vue.AllBidders.filter(function(bidder) {
return !!bidders[bidder.Badge];
});
It is difficult to give an accurate answer with an example that doesn't coincide with the input that your provide.
Anyway, supposing your data structures were more or less like this ones, you could solve the problem with lodash _.intersectionWith.
Intersect both arrays using a comparator that checks the correct object properties. Also, take into account that users must go first in the intersection due to the fact that you're interested in its values.
function comparator(user, bid) {
return user.BidderBadge === bid.Badge;
}
console.log(_.intersectionWith(users, bids, comparator));
Here's the fiddle.

Read html's elements attributes like an array?

I'm thinking for develop a web component form, so... I was wondering my self if it's possible read attributes from a html elements. For example:
<my-component input="3" data-input='"name", "address", "email"' textarea="1" data-textarea='"mensaje"'></my-component>
<script>
while i <= elementattributes.length{
elementattributes[i]
}
</script>
I know that I can access through .getAttribute, but this way will take more code... I just want to be something smart :P
Sorry, my english is poor... I hope you can understand what I want to do :P
:)
If you want to get all of the attributes and their values, you can do something like this:
function getElementAttrs(el) {
var attributes = [].slice.call(el.attributes);
return attributes.map(function(attr) {
return {
name: attr.name,
value: attr.value
}
});
}
var allAttrs = getElementAttrs(document.querySelector('my-component'));
console.log(allAttrs);
<my-component input="3" data-input='name,address,email' textarea="1" data-textarea='"mensaje"'></my-component>
The function getElementAttrs returns an array of objects to you with attribute name-value pairs as keys on the object so that you can loop over it, or just pull by key.
You can use dataset to get specific data attribute
var data = document.querySelector('my-component').dataset.input.split(',');
data.forEach(function(e) {
console.log(e)
})
<my-component input="3" data-input='name,address,email' textarea="1" data-textarea='"mensaje"'></my-component>
If you want to return all attributes from element you can use attributes which return array-like object, but you can create object with name-value from that
var data = document.querySelector('my-component').attributes, attr = {};
Array.from(data).forEach(function(e) {
attr[e.name] = e.value;
});
console.log(attr['data-input']);
<my-component input="3" data-input='name,address,email' textarea="1" data-textarea='mensaje'></my-component>
You can just use .attributes:
document.getElementById("ELEMENT_ID").attributes
This will return an object containing each attribute with its associated value. You can then index the attributes array for specific attributes and use .value for it's corresponding value.

Calling in multiple attributes

still quite new to jQuery / Javascript and am struggling a little.
I have created an attribute called catno that I have assigned to several links. Then I want all instances inside banner-1 to be called into another link separated by a comma. i.e
New Link
I'm just struggling in making this happen. The code I have right now only returns the first catno.
Any help would be great!
JSFIDDLE
<div id="banner-1>
New Link
</div>
$sd('.buy-outfit').attr('href', function() {
return $sd("#banner-1 .add-catno").attr('catno') + ',';
});
Fiddle Demo
var arr_catno = $("#banner-1 a").map(function () { //create array using .map
return $(this).attr('catno'); // add element attribute catno to array
}).get().join(); //use .join() to get comma separated string of array
$('.new-link').attr('href', arr_catno); //assign it to href
.map()
Updated after OP's Comment
Fiddle Demo
$('[id^=banner-] .new-link').attr('href', function () {
return $(this).parent().find('a').map(function () {
return $(this).attr('catno');
}).get().join();
});
Attribute Starts With Selector [name^="value"]
.parent()
.find()
[id^=banner-] --> select all the elements with id starting with banner-
Use $.map to produce an array of catnos and them join them into a string.
$('.new-link').attr('href', function() {
return $.map($(".add-catno"), function (el) {
return $(el).data('catno');
}).join(',');
});
Note in the example that I've changed the catnos attributes to data attributes. Using data is considered good practice for when you want to add arbitrary data to your HTML.
Fiddle

With Underscorejs, how to find whether an array contains another array?

I have this
var matches = bookmarks.filter(function(x) {
return _.contains(x.get("tags"), 'apple');
});
Which will return the bookmark objects that have the apple tags
I want to put an array there instead to pull and all the bookmarks that have the matching values, similar to this
var matches = bookmarks.filter(function(x) {
return _.contains(x.get("tags"), ['apple','orange']);
});
This doesn't work, any way to get it to work?
EDIT: Im sorry, bookmarks is a collection and im trying to return the models that have the apple and orange tags
If tags is a string, your code it would be
return _.indexOf(x.get("tags"), ['apple','orange']) > -1;
Example with indexOf : jsFiddle
If tags is an array, you can use intersection
return _.intersection(['apple','orange'], x.get("tags")).length > 0;
Example with intersection: jsFiddle
There doesn't seem to be a function for that in underscore. However, you can easily combine other functions to accomplish this:
_.mixin({
containsAny: function(arr, values) {
// at least one (.some) of the values should be in the array (.contains)
return _.some(values, function(value) {
return _.contains(arr, value);
});
}
});

Get list of data-* attributes using javascript / jQuery

Given an arbitrary HTML element with zero or more data-* attributes, how can one retrieve a list of key-value pairs for the data.
E.g. given this:
<div id='prod' data-id='10' data-cat='toy' data-cid='42'>blah</div>
I would like to be able to programmatically retrieve this:
{ "id":10, "cat":"toy", "cid":42 }
Using jQuery (v1.4.3), accessing the individual bits of data using $.data() is simple if the keys are known in advance, but it is not obvious how one can do so with arbitrary sets of data.
I'm looking for a 'simple' jQuery solution if one exists, but would not mind a lower level approach otherwise. I had a go at trying to to parse $('#prod').attributes but my lack of javascript-fu is letting me down.
update
customdata does what I need. However, including a jQuery plugin just for a fraction of its functionality seemed like an overkill.
Eyeballing the source helped me fix my own code (and improved my javascript-fu).
Here's the solution I came up with:
function getDataAttributes(node) {
var d = {},
re_dataAttr = /^data\-(.+)$/;
$.each(node.get(0).attributes, function(index, attr) {
if (re_dataAttr.test(attr.nodeName)) {
var key = attr.nodeName.match(re_dataAttr)[1];
d[key] = attr.nodeValue;
}
});
return d;
}
update 2
As demonstrated in the accepted answer, the solution is trivial with jQuery (>=1.4.4). $('#prod').data() would return the required data dict.
Actually, if you're working with jQuery, as of version 1.4.3 1.4.4 (because of the bug as mentioned in the comments below), data-* attributes are supported through .data():
As of jQuery 1.4.3 HTML 5 data-
attributes will be automatically
pulled in to jQuery's data object.
Note that strings are left intact
while JavaScript values are converted
to their associated value (this
includes booleans, numbers, objects,
arrays, and null). The data-
attributes are pulled in the first
time the data property is accessed and
then are no longer accessed or mutated
(all data values are then stored
internally in jQuery).
The jQuery.fn.data function will return all of the data- attribute inside an object as key-value pairs, with the key being the part of the attribute name after data- and the value being the value of that attribute after being converted following the rules stated above.
I've also created a simple demo if that doesn't convince you: http://jsfiddle.net/yijiang/WVfSg/
A pure JavaScript solution ought to be offered as well, as the solution is not difficult:
var a = [].filter.call(el.attributes, function(at) { return /^data-/.test(at.name); });
This gives an array of attribute objects, which have name and value properties:
if (a.length) {
var firstAttributeName = a[0].name;
var firstAttributeValue = a[0].value;
}
Edit: To take it a step further, you can get a dictionary by iterating the attributes and populating a data object:
var data = {};
[].forEach.call(el.attributes, function(attr) {
if (/^data-/.test(attr.name)) {
var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
return $1.toUpperCase();
});
data[camelCaseName] = attr.value;
}
});
You could then access the value of, for example, data-my-value="2" as data.myValue;
jsfiddle.net/3KFYf/33
Edit: If you wanted to set data attributes on your element programmatically from an object, you could:
Object.keys(data).forEach(function(key) {
var attrName = "data-" + key.replace(/[A-Z]/g, function($0) {
return "-" + $0.toLowerCase();
});
el.setAttribute(attrName, data[key]);
});
jsfiddle.net/3KFYf/34
EDIT: If you are using babel or TypeScript, or coding only for es6 browsers, this is a nice place to use es6 arrow functions, and shorten the code a bit:
var a = [].filter.call(el.attributes, at => /^data-/.test(at.name));
Have a look here:
If the browser also supports the HTML5 JavaScript API, you should be able to get the data with:
var attributes = element.dataset
or
var cat = element.dataset.cat
Oh, but I also read:
Unfortunately, the new dataset property has not yet been implemented in any browser, so in the meantime it’s best to use getAttribute and setAttribute as demonstrated earlier.
It is from May 2010.
If you use jQuery anyway, you might want to have a look at the customdata plugin. I have no experience with it though.
As mentioned above modern browsers have the The HTMLElement.dataset API.
That API gives you a DOMStringMap, and you can retrieve the list of data-* attributes simply doing:
var dataset = el.dataset; // as you asked in the question
you can also retrieve a array with the data- property's key names like
var data = Object.keys(el.dataset);
or map its values by
Object.keys(el.dataset).map(function(key){ return el.dataset[key];});
// or the ES6 way: Object.keys(el.dataset).map(key=>{ return el.dataset[key];});
and like this you can iterate those and use them without the need of filtering between all attributes of the element like we needed to do before.
You should be get the data through the dataset attributes
var data = element.dataset;
dataset is useful tool for get data-attribute
or convert gilly3's excellent answer to a jQuery method:
$.fn.info = function () {
var data = {};
[].forEach.call(this.get(0).attributes, function (attr) {
if (/^data-/.test(attr.name)) {
var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
return $1.toUpperCase();
});
data[camelCaseName] = attr.value;
}
});
return data;
}
Using: $('.foo').info();
You can just iterate over the data attributes like any other object to get keys and values, here's how to do it with $.each:
$.each($('#myEl').data(), function(key, value) {
console.log(key);
console.log(value);
});
I use nested each - for me this is the easiest solution (Easy to control/change "what you do with the values - in my example output data-attributes as ul-list) (Jquery Code)
var model = $(".model");
var ul = $("<ul>").appendTo("body");
$(model).each(function(index, item) {
ul.append($(document.createElement("li")).text($(this).text()));
$.each($(this).data(), function(key, value) {
ul.append($(document.createElement("strong")).text(key + ": " + value));
ul.append($(document.createElement("br")));
}); //inner each
ul.append($(document.createElement("hr")));
}); // outer each
/*print html*/
var htmlString = $("ul").html();
$("code").text(htmlString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/prism.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="demo"></h1>
<ul>
<li class="model" data-price="45$" data-location="Italy" data-id="1234">Model 1</li>
<li class="model" data-price="75$" data-location="Israel" data-id="4321">Model 2</li>
<li class="model" data-price="99$" data-location="France" data-id="1212">Model 3</li>
</ul>
<pre>
<code class="language-html">
</code>
</pre>
<h2>Generate list by code</h2>
<br>
Codepen: https://codepen.io/ezra_siton/pen/GRgRwNw?editors=1111
One way of finding all data attributes is using element.attributes. Using .attributes, you can loop through all of the element attributes, filtering out the items which include the string "data-".
let element = document.getElementById("element");
function getDataAttributes(element){
let elementAttributes = {},
i = 0;
while(i < element.attributes.length){
if(element.attributes[i].name.includes("data-")){
elementAttributes[element.attributes[i].name] = element.attributes[i].value
}
i++;
}
return elementAttributes;
}
If you know the name of keys you can also use object destructuring to get values like this
const {id, cat, cid } = document.getElementById('prod').dataset;
You can also skip keys you don't need and get the ones you need like this
const { cid, id } = document.getElementById('prod').dataset;
100% Javascript no jQuery ;)
DOMStringMap :
console.log(document.getElementById('target-element-id').dataset);
or custom variable :
var data = {};
Object.entries(document.getElementById('target-element-id').dataset).forEach(([key, val]) => {
data[key] = val;
});
console.log(data);

Categories

Resources