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/
Related
I'm trying to write this:
$('.circle_div').each(function(){
var $this = $(this),
thisWidth = $this.width();
$this.css('height', thisWidth + 'px');
});
in javascript like this:
var circle_div = document.getElementsByClassName('circle_div');
for (el in circle_div){
var thisWidth = el.style.width;
el.style.height = thisWidth + "px";
}
I also tried for...of and for each, and a regular for loop incrementing var i. The jquery function works but the javascript doesn't. Any idea what I'm doing wrong?
Eeeck. Never use for/in to iterate elements of an array or array-like object (doing so will include other iterable properties in addition to just the array elements).
Plus el in your loop is the index, not the value. You have to use circle_div[index] to get the element from the nodeList. But, you MUST switch to a traditional for loop, not for/in.
var circle_div = document.getElementsByClassName('circle_div');
for (var i = 0; i < circle_div.length; i++) {
var item = circle_div[i];
item.style.height = item.style.width;
}
You also have to remove the + "px" because the units are already there in plain javascript.
For more details on using for loop with document.getElementsByClassName() (including ES6 info), see this other answer: For loop for HTMLCollection elements.
If you convert the NodeList object that returns getElementsByCLassName to a regular array, you can use the Array.prototype.forEach method on it:
// Get the divs, and convert the NodeList to a regular array.
var circle_div = [].slice.call(document.getElementsByClassName('circle_div'), 0);
circle_div.forEach(function (el) {
el.style.height = el.clientWidth + "px";
});
This way looks more similar to your jquery code.
Check the fiddle: http://jsfiddle.net/7ew39phu/
Edit: I realize I should have used clientWidth, instead of style.width. The reason is that style properties seem to be only available if they were set using JavaScript, not if they were set using an css sylesheet.
Anyway, I fixed the code.
var circle_div = document.getElementsByClassName('circle_div');
for (var i=0,l=circle_div.length; i<l; i++){
circle_div[i].style.height = circle_div[i].style.width;
}
this is my code :
html = "";
for (i = 0; i < id_array.length; i++){
html = html.concat($(id_array[i]).clone(true));
}
console.log(html);
The id_array contains 3 ids of the <tr> tag . Instead of the html code from the ids , the result of the html variable is object object object ... Why ? How do I get the html code from this id ?
This is my html code , it is not written by me , it is generated by JQgrid plugin. so i took a picture:
It looks like your want to call outerHTML. In order to do it, you need the native DOM element, you can get it using [0] or get(0) :
var html = "";
for (i = 0; i < id_array.length; i++){
html += $(id_array[i])[0].outerHTML;
}
console.log(html);
clone returns jQuery objects. You don't want to concat them with an empty string. Instead, use an array to store them:
trs = [];
for (i = 0; i < id_array.length; i++){
trs.push($(id_array[i]).clone(true));
}
console.log(trs);
You don't want to use HTML strings when dealing with the DOM.
It seems you may want the outer HTML of the TR elements. Some browsers support it, but not all (and surprisingly not jQuery). In this case you can do something like:
var id_array = ['tr0','tr1','tr2'];
var html = "";
var tbody = $('<tbody>');
for (i = 0; i < id_array.length; i++) {
tbody.append($('#' + id_array[i]).clone(true));
html += tbody.html();
tbody.html('');
}
I have an array of 10 elements. At first I want to shuffle the array elements and display them (my current code does this). Then I want to show an alert message if any of the displayed array elements are clicked. This is the thing I am having problem with. If, I am doing onclick, it's showing me only 1 array element instead of all the 10 array elements and also showing the following error in console Uncaught TypeError: Cannot set property 'onclick' of undefined. My code is (I am using only javascript):
<script>
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var myArray = ['1','2','3','4','5','6','7','8','9','10'];
newArray = shuffleArray(myArray);
for (i=0;i<newArray.length;i++) {
var p = document.write(newArray[i] + "<br >");
p.onclick = showAlert; // this is showing me only 1 array element and also showing error in concole
}
function showAlert() {
alert("onclick Event detected!")
}
</script>
You need to create an actual element, rather than trying to bind events to strings:
for (i=0;i<newArray.length;i++) {
var p = document.createElement('p');
p.innerHTML = newArray[i];
p.onclick = showAlert;
document.body.appendChild(p);
}
http://jsfiddle.net/92fRb/1/
Cannot set property 'onclick' of undefined
Here's your problem... p is undefined.
Why?
Because document.write does not return a DOM element. Actually it does not return anything at all (or, returns undefined).
You want to:
Use document.createElement() to create an element.
Use p.innerHTML to set the content (inner HTML) of your new element.
Append your new element to the document.
Your code can be revised as suggested in #Johan's answer.
for (i=0;i<newArray.length;i++){
var p = document.write("<span class='no'>"+newArray[i] + "</span><br />");
}
function showAlert(){
alert("onclick Event detected!")
}
for(i=0;i<document.getElementsByClassName("no").length;i++){
document.getElementsByClassName("no")[i].onclick=showAlert;
}
Beginner JS here, hope anyone could explain this to me.
1) Why does this not work:
var allSpans = document.getElementsByTagName('span');
allSpans.onclick = function() {
alert('hoo');
};
2) or if I have all the innerHTML from spans in an array and I try this:
var allSpans = document.getElementsByTagName('span');
var arrayNumbers = [];
for (var i = 0; i < allSpans.length; i++) {
var operator = allSpans[i].innerHTML;
}
arrayNumbers.onclick = function() {
alert('hoo');
};
onclick is a property of HTMLElementNode objects. getElementsByTagName returns a NodeList. Assigning a property to a NodeList doesn't assign it to every member of that list.
Exactly the same, except you are dealing with an Array instead of a NodeList.
You have to iterate through the returned list
var allSpans = document.getElementsByTagName('span');
for ( var i = 0; i < allSpans.length; i += 1 ) {
allSpans[i].onclick = function (event) {
alert('hoo');
};
}
To answer your first question, you have to add this on each node instead of the nodeList, which is what you're getting when you call document.getElementsByTagName. What you're looking for is:
for(var i = 0; i < allSpans.length; i++){
allSpans[i].onClick = function(){
alert('hoo');
};
}
You have a similar issue in the second question, except it doesn't appear as if you're actually adding anything to the arrayNumbers array, so even if you looped through that, you wouldn't get the expect events on click.
I have an array of strings in Javascript like `var elements = ["string1", "string2"]; The array is created dynamically so it could contain any number of strings. I want to associate a counter to each element of the array. The counter will increment or decrement during the webpage's life.
I was going to try element["string1"].counter = 1; but it didn't work.
What's a good way to implement this?
If you had an array var elements = ["string1", "string2"], you could not access an element with elements["string1"], you are using the value not the index. elements[0] is the correct form of access to the element, using the numerical key.
Even then, strings are special types of object and do not appear to take additional parameters readily, at least not when I tested a moment ago. Which is odd.
You could quickly knock the array in to a set of objects with separate text and counter components.
var elements = ["string1", "string2"];
var elementsWithCounter = [];
for(var index = 0; index < elements.length; index++) {
elementsWithCounter[i] = { text: elements[index], counter: 1 };
}
You could also create a "hash table" using a plain object such as:
var counter = {};
for(var i = elements.length; i--; ) {
counter[elements[i]] = 1;
}
Then you could increment the counter with:
counter['string1'] += 1;
or
counter[elements[0]] += 1;
This might help you.
elementArray = ["string1", "string2"]
function setCounter(str, val) {
for (var i = 0; i < elementArray.length; i++) {
if (str === elementArray[i]) elementArray[i].counter = val;
}
}
function getCounter(str) {
for (var i = 0; i < elementArray.length; i++) {
if (str === elementArray[i]) return elementArray[i].counter;
}
}
setCounter("string1", 5);
getCounter("string1");
Alternatively just access elementArray[index].counter
Javascript primitives/built in objects can't have properties/attributes added to their prototype (i.e. String.prototype.counter = -1 doesn't work correctly). Image, String, Date, Array all can't have properties added.
Maybe instead of a string you should make it an object, similar to what Orbling has posted.