Using innerHTML with querySelectorAll - javascript

I want to use something similar to the following to clear errors in a form upon a resubmission attempt:
document.querySelectorAll("#form-error-name, #form-error-email, #form-error-tel, #form-error-dob, #form-error-password, #form-error-goal").innerHTML= "";
...But the contents of the divs isn't cleared. What am I doing wrong?

The question wants .innerHTML, but that's not valid on input; you actually want .value. The appropriate modern answer would be
[... document.querySelectorAll('input')]
.map(i => i.value = '');

You'll need to loop through the results
var errors = document.querySelectorAll(
"#form-error-name,
#form-error-email,
#form-error-tel,
#form-error-dob,
#form-error-password,
#form-error-goal");
[].forEach.call(errors, function(error) {
error.innerHTML = '';
});
querySelectorAll doesn't return an array, but a node list, which doesn't have a forEach method on its prototype.
The loop above is using the forEach method on the array object's prototype on the nodeList object.

Try this:
var x = document.querySelectorAll("#form-error-name, #form-error-email, #form-error-tel");
var i;
for (i = 0; i < x.length; i++) {
x[i].innerHTML = "";
}
See, if that helps.

Another way to do this is to call forEach directly on the results of querySelectorAll, which returns NodeList resutls:
query_selector = "#form-error-name, #form-error-email, #form-error-tel, #form-error-dob, #form-error-password, #form-error-goal"
document.querySelectorAll(query_selector).forEach(node => node.innerHTML = "")

Related

document.getElementsByTagName not working

I would like to use document.getElementsByTagName('input')
to set as required (or unset it) for a list of inputs.
is it possible?
I've tried:
document.getElementsByTagName('input').required = false;
or (for a different purpose)
document.getElementsByTagName('input').value = ""
but it doesn't seem work.
Moreover: is it possible to catch a certain type of input (i.e. text or radio)?
Thank you!!!
ObOnKen
getElementsByTagName() returns a collection of elements so you need to iterate over the collection...
var elements = document.getElementsByTagName('input');
for(var i = 0; i < elements.length; i++)
{
if(elements[i].type == "text")
{
elements[i].value = "";
}
}
getElementsByTagName() returns a live HTMLCollection. If you want to do something to each item returned, you'll have to explicitly iterate across them:
var inputs = table.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
inputs[i].required = false;
}
However, if you use some libraries, you may be able to operate on each of the contents of a collection (or, as some of the libraries call them, selection) en-masse with a syntax as you seem to expect.
You should use for loop for iterating all inputs, because document.getElementsByTagName returns a HTMLCollection of elements with the given tag name.
var values = document.getElementsByTagName('input');
for (var i = 0; i < values.length; i++) {
values[i].required = false;
}
To catch a certain type of input:
var textInput = document.querySelector("input[type=text]");
querySelector returns the first element within the document.

Selecting inside a DOM element

This is the html code
<div class="extra-sub-block sub-block-experience">
<h6 style="display:inline;" id="exp-pos-0" class="extra-sub-block-head sub-block-head-experience">CEO</h6>
</div>
<div class="extra-sub-block sub-block-experience">
<h6 style="display:inline;" id="exp-pos-1" class="extra-sub-block-head sub-block-head-experience">COO</h6>
</div>
There are several such similar structures. Now I try to extract the values from each block.
var temp=document.getElementsByClassName('sub-block-experience');
var result=$(temp[0]+"#exp-pos-0");
This throws an error. I followed selecting element inside another DOM
I also tried
var temp=document.getElementsByClassName('sub-block-experience');
var result=temp[0].find('h6');
This doesn't work as well. What am I doing wrong here. Help?
For extracting the values from all blocks, you can use .map() function as follows:
var results = $('.extra-sub-block-head').map(function(){
return $(this).text();
})
Demo
side note: Since id is unique in a document, you can directly access the element using id selector like var result= $("#exp-pos-0");instead of var result=$(temp[0]+"#exp-pos-0");
Try, var result=$(temp[0]).find('h6');
Even, in the documentation link that you gave in question, it shows that you should wrap your result from document.getElementById in $() to be applied with jQuery. What it does is, that it converts the native javascript object into a jquery object.
Demo
function testIt(){
var tags, index;
tags = document.getElementsByTagName('h6');
for (index = 0; index < inputs.length; ++index) {
//do something ...
}
}
If I am correct you are trying to get ceo and coo?.If that's the case then with jquery:
var x= $('.extra-sub-block h6');
//values are
$(x[O]).html();
$(x[1]).html();
You could also use plain javascript:
var result = document.querySelectorAll('.sub-block-experience h6');
Or if you like it separate:
var temp = document.querySelectorAll('.sub-block-experience');
var result = [];
for(var i = 0, elem; elem = temp[i]; i++) {
result = result.concat(elem.querySelectorAll('h6'));
}
But be aware of the browser compatability of querySelectorAll and querySelector.

getElementsByClassName produces error "undefined" [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 8 years ago.
I have several textboxes with the class output. I would like to be able to print their values as a plain HTML list in a div with ID combined. Right now, I have the following code:
function doCombine() {
document.getElementById('combined').innerHTML =
document.getElementsByClassName('output').value + ",";
}
Yet, when I run the function, i get the error message undefined,. When i add a [0] before .value, it works, but only the value of the first textbox is showing up. I read somewhere that [i] will show all the values, but that doesn't seem to work.
What am I doing wrong?
getElementsByClassName
Returns a set of elements which have all the given class names. When called on the document object, the complete document is searched, including the root node. You may also call getElementsByClassName on any element; it will return only elements which are descendants of the specified root element with the given class names.
So you should be doing
var elements = document.getElementsByClassName('output');
var combined = document.getElementById('combined');
for(var i=0; i < elements.length; i++) {
combined.innerHTML += elements[i].value + ",";
}
getElementsByClassName returns an array-like object, not a single element (notice the plural in the name of the function). You need to iterate over it, or use an array index if you just want to operate on the first element it returns:
document.getElementsByClassName('output')[0].value + ","
getElementsByClassName returns a set of elements. You need to iterate over it:
var elems = document.getElementsByClassName("output");
for(var i=0; i<elems.length; i++) {
combined.innerHTML += elems[i].value + ",";
}
That's why adding [0] works, because you are accessing the first object in this set.
This function will return ALL the elements with that name, because"name" attribute is not unique, so it returns an list (nodeList, to be exact).
To print out ALL the values, you need to add a loop. Something like
var finalvar = "";
var arr = document.getElementsByClassName('output');
for (i=0;i<arr.length;i++) {
finalval = finalval + arr[i].value;
}
document.getElementById('combined').innerHTML = finalval
getElementsByClassName will return a set of elements. Refer: https://developer.mozilla.org/en-US/docs/Web/API/document.getElementsByClassName#Summary. Some browsers return HTMLCollection and some browsers return NodeList. https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection#Browser_compatibility But they both have length property and item method in common. So you can iterate like this.
function doCombine()
{
var listOfOutputElements = document.getElementsByClassName('output');
var combinedItem = document.getElementById('combined');
for (var i = 0; i < listOfOutputElements.length; i += 1) {
combinedItem.innerHTML += listOfOutputElements.item(i).innerHTML;
}
}
Try this :
<script type="text/javascript">
function doCombine()
{
var combined = document.getElementById('combined');
var nodeList = document.getElementsByClassName('output');
var nodeListLength = nodeList.length;
for (i=0;i<nodeListLength;i++) {
combined.innerHTML += nodeList[i] + ',';
}
</script>
getElementsByClassName returns an NodeList. So you won't be able to call the value method on it. Try the following:
function doCombine() {
var combined = document.getElementById('combined');
var outputs = document.getElementsByClassName('output');
for(var i=0; i<outputs.length; i++){
combined.innerHTML += outputs[i].value + ',';
}
}
http://jsfiddle.net/FM3qH/

I want to loop through an array and modify attributes

Here is my code
var input_buttons = ["#one","#two","#three"];
var substr = input_buttons.split(',');
for(var i=0; i< substr.length; i++)
{
substr.attr('value', '');
}
Why doesn't this work?
Your first problem is calling split(',') on an array. However, if you just want to set the values of all those to a blank string you can do:
$('#one,#two,#three').val('');
If you want to set different values you'd need to loop through:
$('#one,#two,#three').each(function() {
// this == the HTML node (not a jQuery element)
this.value = someValue; // someValue would set outside
};
You already have an array, there is nothing to split, this only works on strings. You'd also have to pass the ID to jQuery before you can cal attr. In this case val is even better.
var input_buttons = ["#one","#two","#three"];
for(var i=input_buttons.length; i--;) {
$(input_buttons[i]).val('');
}
But shorter would be using the multiple selector:
$('#one, #two, #three').val('');
or if you already have the array, create a string by joining the IDs:
$(input_buttons.join(',')).val('');
I'm wondering why you are calling:
var substr = input_buttons.split(',');
By the nature of your input_buttons, you already have an array. All you should have to do is:
var input_buttons = ["#one","#two","#three"];
for(var i=0; i< substr.length; i++)
{
$(input_buttons[i]).attr('value', '');
}
var input_buttons = ["#one","#two","#three"];
$.each(input_buttons, function(idx, value) {
$(value).val('');
});
Or even better and shorter:
$('#one, #two, #three').val('');
You could also give those elements a common class name and then use this:
$('.className').val('');
your array contains just the id but not the actual object
try this
var input_buttons = ["#one","#two","#three"];
for(var i=0; i< input_buttons.length; i++)
{
$(input_buttons[i]).removeAttr('value');
}
input_buttons is already an array - don't split it.
To use .attr you need it to be a jquery object, so call $(input_buttons[i]).attr
Try the following to remove an attribute:
var input_buttons = ["#one","#two","#three"];
for(var i=0; i< input_buttons.length; i++)
{
$(input_buttons[i]).removeAttr('value');
}
The reason your code does not work is in the overloading of jQuery functions. .attr('value', '') evaluates to .attr('value'), which returns the value of value as opposed to setting it. The reason is that '' evaluates to false.

javascript - get all anchor tags and compare them to an array

I have been trying forever but it is just not working, how can I check the array of urls I got (document.getElementsByTagName('a').href;) to see if any of the websites are in another array?
getElementByTagName gives you a nodelist (an array of nodes).
var a = document.getElementsByTagName('a');
for (var idx= 0; idx < a.length; ++idx){
console.log(a[idx].href);
}
I really suggest that you use a frame work for this, like jquery. It makes your life so much easier.
Example with jquery:
$("a").each(function(){
console.log(this.href);
});
var linkcheck = (function(){
if(!Array.indexOf){
Array.prototype.indexOf = function(obj){
for(var i=0; i<this.length; i++){
if(this[i]===obj){
return i;
}
}
return -1;
}
}
var url_pages = [], anchor_nodes = []; // this is where you put the resulting urls
var anchors = document.links; // your anchor collection
var i = anchors.length;
while (i--){
var a = anchors[i];
anchor_nodes.push(a); // push the node object in case that needs to change
url_pages.push(a.href); // push the href attribute to the array of hrefs
}
return {
urlsOnPage: url_pages,
anchorTags: anchor_nodes,
checkDuplicateUrls: function(url_list){
var duplicates = []; // instantiate a blank array
var j = url_list.length;
while(j--){
var x = url_list[j];
if (url_pages.indexOf(x) > -1){ // check the index of each item in the array.
duplicates.push(x); // add it to the list of duplicate urls
}
}
return duplicates; // return the list of duplicates.
},
getAnchorsForUrl: function(url){
return anchor_nodes[url_pages.indexOf(url)];
}
}
})()
// to use it:
var result = linkcheck.checkDuplicateUrls(your_array_of_urls);
This is a fairly straight forward implementation of a pure JavaScript method for achieving what I believe the spec calls for. This also uses closures to give you access to the result set at any time, in case your list of urls changes over time and the new list needs to be checked. I also added the resulting anchor tags as an array, since we are iterating them anyway, so you can change their properties on the fly. And since it might be useful to have there is a convenience method for getting the anchor tag by passing the url (first one in the result set). Per the comments below, included snippet to create indexOf for IE8 and switched document.getElementsByTagName to document.links to get dynamic list of objects.
Using Jquery u can do some thing like this-
$('a').each(function(){
if( urls.indexOf(this.href) !- -1 )
alert('match found - ' + this.href );
})
urls is the your existing array you need to compare with.

Categories

Resources