I'd like to get all <input /> elements with the placeholder property set, how could I do this without jquery? it should support IE6+, and other popular browsers.
Assuming all the fields have an ID
DEMO
var fieldsWithPlaceholder = [];
var inputs = document.getElementsByTagName("input");
for (var i=0, n=inputs.length;i<n;i++) {
if (inputs[i].getAttribute("placeholder") !=null) {
fieldsWithPlaceholder.push(inputs[i].id);
}
}
alert(fieldsWithPlaceholder);
Update: you can as posted elsewhere test for null, undefined or blank in one go:
if (inputs[i].getAttribute("placeholder")) { // there is something there
Use getElementsByTagName, filter for those with a placeholder property value that isn't undefined.
Incidentally, there is a big difference between attributes and properties, which are you really after? If you are setting an attribute called placeholder in the HTML, then you should use getAttribute. However, if you are setting the property of a DOM element (which is what I presumed from your post) then you should use the property directly. Hopefully you aren't mixing the two.
In some browsers, attributes and properties are kept synchronised but in others they aren't. For example, Firefox will not create element properties for non–standard attributes (i.e. those that aren't specified in the related markup standard), nor will it create or modify standard attributes based on property changes in versions that aren't consistent with HTML5.
get all the elements of type input first
document.getElementsByTagName("input")
loop over the above list and then use the
getAttribute on each of the element as follows getAttribute("placeholder") if it is not null or undefined then the input has it set.
Try something like this:
var myEls = [],
allEls = document.getElementsByTagName('input');
for (var i=0; i < allEls.length; i++) {
if (allEls[i].placeholder)
myEls.push(allEls[i]);
}
Related
This is an example of working with attribute nodes. Why would I need to use attribute nodes when I am accessing the DOM in JavaScript
Learning how to setAtttribute,getAttribute,removeAttribute
Need to know why and when I use this ?
if(document.getElementById("plc").hasAttribute("class"))
penguin.setAttribute("class", "hidden");
var penguin = document.getElementById("plc");
alert(document.getElementById("plc").getAttribute("class"));
getAttribute, setAttribute, and removeAttribute are technically called methods, and they act on the DOM node by manipulating the attributes. The DOM node itself is what you've assigned to your variable penguin (but it should be assigned before you use it).
One common use case has to do with storing bits of data on a node. You can set that information and retrieve it later.
Say you have a couple penguins.
<div id='penguin-crowd'>
<div class='penguin' data-species='emperor'></div>
<div class='penguin' data-species='king'></div>
</div>
Now you want to list their species.
let penguins = document.getElementsByClassName('penguin');
for (let i = 0; i < penguins.length; i++) {
let species = penguin[i].getAttribute('data-species');
console.log(`This penguin's species is ${species}`);
}
Result:
// This penguin's species is emperor
// This penguin's species is king
Add another penguin to the crowd.
let penguinCrowd = document.getElementById('penguin-crowd');
let newPenguin = document.createElement('div');
newPenguin.classList.add('penguin');
newPenguin.setAttribute('data-species','emperor');
penguinCrowd.appendChild(newPenguin);
Now you have
<div id='penguin-crowd'>
<div class='penguin' data-species='emperor'></div>
<div class='penguin' data-species='king'></div>
<div class='penguin' data-species='emperor'></div>
</div>
removeAttribute removes the whole attribute from a node, so if for some reason that needs to happen, it's your go-to method.
setAttribute() for custom attributes you create ie node.className vs node.userName. className is a standard attribute vs userName is custom. For example, node.setAttribute('userName', 'someName') vs node.className = 'someName'.
getAttribute() gives you back attributes of the DOM vs properties like node.id. Most of the time the values are the same, but there are cases when they aren't. For example input's checked property: getAttribute() will retrieve checked/empty string, but input.checked will come back with true/false. There was more discussion on this in this question you can check out getAttribute() versus Element object properties?
removeAttribute() is simply to remove any attribute instead of setting it to null. In the official docs it says you should use removeAttribute() instead of setting the attribute value to null either directly or using setAttribute(). Many attributes will not behave as expected if you set them to null.
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).
I am new at JavaScript so I think my problem may be simple.
This works:
var convId = document.getElementById("wrapper");
convId.setAttribute("align","right");
But when I try to make it more specific:
var convId = document.getElementById("wrapper");
var convIdDl = convId.getElementsByTagName("dl");
convIdDl.setAttribute("align","right");
my definition list doesn't align to the right.
I have checked the HTML and CSS and everything is correct, but that shouldn't even matter
JavaScript overwrites them both.
The getElementsByTagName method returns a collection (to be more specific, a NodeList). You need to specify which element of that collection you want to use (just like you would when accessing an element in an array). Here I'm assuming you want the first:
convIdDl[0].setAttribute("align", "right");
As noted in the comments, you should definitely not be using the align attribute. CSS should be used in all cases.
The getElementsByTagName() function returns a collection of DOM elements, so you'll probably want to iterate through that and set the attribute on each element individually.
for(var i = 0; i < convIdDl.length; i++) {
convIdDl[i].setAttribute("align", "right");
}
I am trying to check whether the a css class is used inside the DOM or not. So, I have
var x = document.getElementsByClassName('classname');
When I print x out, I get a [object NodeList] for classes that exist on the page and classes that dont. Is there a property of x that I can access ? Like the tag name or something. Would be great if somebody can tell me the different properties of x and the ways I can access them.
Thank you :)
Notice that it's plural:
var x = document.getElementsByClassName('classname');
^
You need to iterate over x to get the individual elements:
for (var i = 0; i < x.length; i++) {
var element = x[i];
console.log(element);
}
Make sure to add fallback support for Internet Exploder: http://ejohn.org/blog/getelementsbyclassname-speed-comparison/
If you just want to check for the presence of a class in the document, you can also use querySelector.
var x = document.querySelector('.classname');
It returns null if no elements have that class, otherwise the first element with that class name. If you want all elements using classname:
var x = document.querySelectorAll('.classname');
Now x is null if the class is not used in the document, otherwise a Nodelist, containing all elements with class classname, which can be iterated the way Blender showed. In that iteration you can, for example, retrieve the elements tagName or its id. Like:
for (var i=0;i<x.lenght;(i=i+1)){
console.log(x[i].id + ': ' + x[i].tagName);
}
document.querySelector is available in all modern browsers, and for IE version 8 and up.
I almost always use document.querySelector (which: "Returns the first element within the document that matches the specified group of selectors"), which returns an element object and it's.
I don't know why but in my Chrome's console I write:
var img = document.getElementsByClassName('image__pic');
img[0]...
img[0], despite its happy existance, it doesn't generate any further attributes/methods to use in the completion window. Like there were none (even though I could use img[0].src for instance)
On the other hand:
var imgq = document.querySelector('.image__pic')
Gives me very useful autocompletion on the Console:
As far as its browser support it is phenomenal:
It is also less tricky to use, because getElementsByClassName returns an HTMLCollection, which is a little beast of its own.
Another plus for querySelector is its versatility: any kind of CSS selector goes!
On the negative side, querySelector is a bit slower, but I think it's worth it.
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