Say I'm looking for all elements with an attribute 'data-language', whose value begins with 'java' (would match both 'java' and 'javascript'). I know how to do this:
$('[data-language^="java"]')
But my question is: how do I get all elements that have an attribute (not the value of the attribute, but the actual attribute name itself) beginning with something? For example:
all elements that have an attribute name beginning with "data-s", or
all elements that have data attributes at all (attributes beginning with "data-").
There is no shortcut, you may use the attributes collection :
$(someselector).filter(function(){
var attrs = this.attributes;
for (var i=0; i<attrs.length; i++) {
if (attrs[i].name.indexOf("someStartOfName")==0) return true;
}
return false;
});
jQuery has a nice function for this.
http://api.jquery.com/data/
$("div").data() // returns all data attributes to this div
Related
Simply, i'm trying to use jQuery to append a numeric value (currently stored in an array) to the end of the "id" attribute of a number of specified elements.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink').attr("id", // Append modCount[0].toString() to each existing ID);
The struggle I am having is in working out how to append the numeric value as opposed to simply set the ID equal to the numeric value. I don't want to lose the existing ID.
In the example, the preferred resulting ID's should be:
#headerAfirstLink1, #headerAsecondLink1, #headerAthirdLink1, #headerAfourthLink1
(If modCount[0] == 1).
I'm sure it is crucifyingly simple but would appreciate some guidance.
Thanks
You can use .attr(attributeName, function) syntax to update the attribute value for each of the respective element.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink')
.attr("id", function(index, oldId) {
// oldId is the attribute value
return oldId + modCount[0];
});
Just in case, to update the attribute of all the elements whose ID starts with header, you can use attribute starts with selector.
$('[id^="header"]').attr('id', function(index, oldId) {
return oldId + modCount[0];
});
Try to use .attr("attrName" , callBack) signature to achieve what you want.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink')
.attr("id", function(_,id){
return id + modCount[0];
});
Don't confuse the first parameter passed with callBack. It is index. I just used an underscore there as it is not required in our case. Simply to hide its visual.
Or the best/maintainable approach would be setting a common class (ex: test) to those four elements and use a class selector there instead of multiple selector.
$('.test').attr('id', function(_, id) {
return id + modCount[0];
});
Say I'm looking for all elements with an attribute 'data-language', whose value begins with 'java' (would match both 'java' and 'javascript'). I know how to do this:
$('[data-language^="java"]')
But my question is: how do I get all elements that have an attribute (not the value of the attribute, but the actual attribute name itself) beginning with something? For example:
all elements that have an attribute name beginning with "data-s", or
all elements that have data attributes at all (attributes beginning with "data-").
There is no shortcut, you may use the attributes collection :
$(someselector).filter(function(){
var attrs = this.attributes;
for (var i=0; i<attrs.length; i++) {
if (attrs[i].name.indexOf("someStartOfName")==0) return true;
}
return false;
});
jQuery has a nice function for this.
http://api.jquery.com/data/
$("div").data() // returns all data attributes to this div
I'm used to JQuery but not to pure Javascript.
I have this:
document.getElementById("div-id a").style.javascript_property = "color: red;";
OF COURSE it doesn't work.
What i want is that all a-tags in one specific div with an id='div-id' to become red.
in jquery i would write:
$('#div-id a').css('color', 'red');
But i need it in pure js.
Use:
var div = document.getElementById("div-id");
var list = div.getElementsByTagName("a");
for (var i = 0; i < list.length; i++) {
list[i].style.color = "red";
}
The getElementById method takes a string representing an id, not a selector. The clue is in the name. The querySelectorAll method takes a string representing a selector, but it returns a nodeList, so you would have to loop over it like an array.
The property name which you have called javascript_property needs to match the CSS property name (with hyphenated-words turned into camelCase) (so it should be "color").
The value you give it needs to match the CSS properties value, not the entire rule (so "red").
None of this, however, is pure JavaScript. It is DOM (except for querySelectorAll which is from the Selectors API).
Using only pure JavaScript, what is the most efficient way to select all DOM elements that have a certain data- attribute (let's say data-foo).
The elements may be different, for example:
<p data-foo="0"></p><br/><h6 data-foo="1"></h6>
You can use querySelectorAll:
document.querySelectorAll('[data-foo]');
document.querySelectorAll("[data-foo]")
will get you all elements with that attribute.
document.querySelectorAll("[data-foo='1']")
will only get you ones with a value of 1.
document.querySelectorAll('[data-foo]')
to get list of all elements having attribute data-foo
If you want to get element with data attribute which is having some specific value e.g
<div data-foo="1"></div>
<div data-foo="2"></div>
and I want to get div with data-foo set to "2"
document.querySelector('[data-foo="2"]')
But here comes the twist ... what if I want to match the data attirubte value with some variable's value? For example, if I want to get the elements where data-foo attribute is set to i
var i=2;
so you can dynamically select the element having specific data element using template literals
document.querySelector(`[data-foo="${i}"]`)
Note even if you don't write value in string it gets converted to string like if I write
<div data-foo=1></div>
and then inspect the element in Chrome developer tool the element will be shown as below
<div data-foo="1"></div>
You can also cross verify by writing below code in console
console.log(typeof document.querySelector(`[data-foo="${i}"]`).dataset('dataFoo'))
why I have written 'dataFoo' though the attribute is data-foo reason dataset properties are converted to camelCase properties
I have referred below links:
MDN: data-*
MDN: Using data attributes
Try it → here
<!DOCTYPE html>
<html>
<head></head>
<body>
<p data-foo="0"></p>
<h6 data-foo="1"></h6>
<script>
var a = document.querySelectorAll('[data-foo]');
for (var i in a) if (a.hasOwnProperty(i)) {
alert(a[i].getAttribute('data-foo'));
}
</script>
</body>
</html>
Here is an interesting solution: it uses the browsers CSS engine to to add a dummy property to elements matching the selector and then evaluates the computed style to find matched elements:
It does dynamically create a style rule [...] It then scans the whole document (using the
much decried and IE-specific but very fast document.all) and gets the
computed style for each of the elements. We then look for the foo
property on the resulting object and check whether it evaluates as
“bar”. For each element that matches, we add to an array.
Native JavaScript's querySelector and querySelectorAll methods can be used to target the element(s). Use a template string if your dataset value is a variable.
var str = "term";
var term = document.querySelectorAll(`[data-type=${str}]`);
console.log(term[0].textContent);
var details = document.querySelector('[data-type="details"]');
console.log(details.textContent);
<dl>
<dt data-type="term">Thing</dt>
<dd data-type="details">The most generic type.</dd>
</dl>
var matches = new Array();
var allDom = document.getElementsByTagName("*");
for(var i =0; i < allDom.length; i++){
var d = allDom[i];
if(d["data-foo"] !== undefined) {
matches.push(d);
}
}
Not sure who dinged me with a -1, but here's the proof.
http://jsfiddle.net/D798K/2/
While not as pretty as querySelectorAll (which has a litany of issues), here's a very flexible function that recurses the DOM and should work in most browsers (old and new). As long as the browser supports your condition (ie: data attributes), you should be able to retrieve the element.
To the curious: Don't bother testing this vs. QSA on jsPerf. Browsers like Opera 11 will cache the query and skew the results.
Code:
function recurseDOM(start, whitelist)
{
/*
* #start: Node - Specifies point of entry for recursion
* #whitelist: Object - Specifies permitted nodeTypes to collect
*/
var i = 0,
startIsNode = !!start && !!start.nodeType,
startHasChildNodes = !!start.childNodes && !!start.childNodes.length,
nodes, node, nodeHasChildNodes;
if(startIsNode && startHasChildNodes)
{
nodes = start.childNodes;
for(i;i<nodes.length;i++)
{
node = nodes[i];
nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length;
if(!whitelist || whitelist[node.nodeType])
{
//condition here
if(!!node.dataset && !!node.dataset.foo)
{
//handle results here
}
if(nodeHasChildNodes)
{
recurseDOM(node, whitelist);
}
}
node = null;
nodeHasChildNodes = null;
}
}
}
You can then initiate it with the following:
recurseDOM(document.body, {"1": 1}); for speed, or just recurseDOM(document.body);
Example with your specification: http://jsbin.com/unajot/1/edit
Example with differing specification: http://jsbin.com/unajot/2/edit
HI! I have a problem with changing the name of a select element. I have about 28 select elements generated on the page. Each of these select elements has been given the name "dropdown". I use this name to calculate the total based on the option selected.
But when i pass this information to a php page, it shows only the last select element. To overcome this i need to have all the select tags labelled as "dropdown[]" onsubmit. This is because i need "dropdown" for javascript to read it and i need "dropdown[]" for php to process it.
<select name="dropdown">
<option>
<option>
<option>
</select>
should be changed to :
<select name="dropdown[]">
<option>
<option>
<option>
</select>
while validating the form in the end. How do i go about it? I dont use ids along with the name, because I think it might make it complex.
I would recommend you to stay with the 'dropdown[]' name, then you can use the getElementsByName function, which will return you an array that you can iterate, of elements with the given name in the document:
var dropdownArray = document.getElementsByName('dropdown[]'),
i, element, n = dropdownArray.length;
for (i = 0; i < n; i++) {
element = dropdownArray[i];
// you can check the value of each element here...
}
Edit: Modifying your code:
function addup(){
var tot = 0, i, // i declaration was missing
dropdowns = document.payment.elements['dropdown[]'];
for(i = 0;i<dropdowns.length;i++) {
//alert(i);
var find = dropdowns[i];
var check = find.options[find.selectedIndex].value;
//alert(check);
if(check.substring(0,3)=='pay') {
// not using eval anymore
var tot1 = document.payment.elements[check.substring(4)+'_amount'].value;
//alert(tot1);
tot += +tot1; // unary plus operator to convert to number
}
document.payment.total_amount.value=tot;
calcTotal();
}
}
I think you're approaching this problem wrong. You should probably use "id" to uniquely identify elements. Then you can use one of the many libraries available for free (jQuery, dojo query, ....) to provide you a nicer way to select elements from the page. Either by giving your specific "<select>" elements class names, or just by finding all the "select" elements on the page.
I'm completely in the dark as to why "[]" at the end of the name would make a difference for you. But I'm not familiar with php.
Using this box because i could display the code.
If i named the element as "dropdown[]" I would be getting an error like in this case:-
function addup(){
var tot=0;
for(i=0;i<(document.payment.dropdown.length);i++)
{
//alert(i);
var find=document.payment.dropdown[][i];
var check=find.options[find.selectedIndex].value;
//alert(check);
if(check.substring(0,3)=='pay')
{
var other="document.payment."+check.substring(4)+"_amount.value";
var tot1=eval(other);
//alert(tot1);
tot+=parseInt(tot1);
}
document.payment.total_amount.value=tot;
calcTotal();
}
}
Pardon the shabby code, but this doesnt seem to work if i name it as "dropdown[]". So i need the name to be "dropdown" in the beginning and then it should change to "dropdown[]" onsubmit.
I've just found your question.
Why to just add a id (example 'itsID') tag to your select and then point it to change its name with:
var ref = document.getElementById('itsID');
ref.name = "dropdown[]";
It works for me with ref.