What is wrong at this part of script:
function refreshLabels() {
// loop through all document elements
var allnodes = document.body.getElementsByTagName("*");
for (var i=0, max=allnodes.length; i < max; i++) {
// get id current elements
var idname = allnodes[i].id;
// if id exists, set get id current elements
if (idname !== '') {
allnodes[i].textContent = multilang.get(idname);
}
}
}
Firebug always say:
"TypeError: allnodes[i] is undefined"
I can't find any solution to fix this - is this part wrong?
"for (var i=0, max=allnodes.length; i < max; i++)"
Btw., also Chrome say it - so its not just a FF problem.
Your issue with changing the textContent is that you are actually mutating the node child's nodes of the allnodes array and thereby also mutating the length of the allnodes array, reducing its size so that the loop continues running past the end of the newly shortened array.
Refer to MDN web docs for what textContent is doing:
function refreshLabels() {
// loop through all document elements
var allnodes = document.body.getElementsByTagName("*");
console.log(allnodes.length)
for (var i = 0, max = allnodes.length; i < max; i++) {
// get id current elements
var idname = allnodes[i].id;
// if id exists, set get id current elements
if (idname !== '') {
allnodes[i].textContent = idname;
console.log(allnodes.length) // this length will change
}
}
}
Related
This is my code
var menuLi=[];
$(window).load(function() {
var menuUl = document.getElementById("sub");
menuLi = menuUl.getElementsByTagName("LI");
var len = menuUl.childNodes.length;
nSpan = document.createElement("SPAN");
var findUl;
for (var i = 0; i < len; i++) {
findUl = menuLi[i].getElementsByTagName("UL");
liLen = findUl.length;
if (liLen > 0) {
menuLi[i].classList.add("myNew");
}
}
});
The above is my code which throws error menuLi[i] is undefined.
Problem:
In fact you are looping using the wrong length.
Explanation:
Because the menuLi.length is lower than menuUl.childNodes.length, as menuUl.childNodes will contain all the li inside menuUl and their children.
So menuUl.childNodes.length is the number of li elements multiplied by the number of elements in each li.
So i will get greater than the menuLi.length, and that explains why you got menuLi[i] is undefined, because if you have only 5 li in menuUl and for example you are trying to get menuLi[8], where menuLi[8] is undefined.
Solution:
So just use:
var len = menuLi.length;
You are looping from 1 to menuUl.childNodes.length using i, but you are indexing straight into menuUl[i]. Do you mean menuUl.childNodes[i]?
So, I have this function it takes two arrays of objects, workArr and arr, and match there id property and then add up the hours property to store in the workArr array.
var workArr = [];
var arr = [];
foundID = [];
function blah()
{
var i = 0;
var j = 0;
//Add up the hours
for( i=0; i < workArr.length ; i++)
{
for( j=0; j < arr.length ; j++)
{
//Makesure the id's match and the week is within the given time frame
//ALSO make sure the id hasn't already be visited
if( cond1 && !(isInArray(workArr[i].id)))
{
workArr[j].total = workArr[j].total + arr[j].hrs;
foundId.push(workArr[j].id);
}//end if id === id
}//end for j loop
}//end for i loop
printArr(foundId);
}//End blah()
//Checks if the given id has already be found
//returns true or false
function isInArray(id) {
return foundID.indexOf(id) > -1;
}
The problem is when I print out my already visited id array, once this function ends, there are duplicates in it, and there shouldn't be because if a duplicate is found it breaks the if condition and doesn't get added to the already found id's. So somehow my if condition isn't weeding out the already visited id's. Please help me solve this seemingly easy problem.
Solved with the help from the comments should be workArr[i] not workArr[j]
if( cond1 && !(isInArray(workArr[i].id)))
{
workArr[i].total = workArr[i].total + arr[j].hrs; // workArr[i]
foundId.push(workArr[i].id); // workArr[i]
}//end if id === id
here is the deal, i have the following jquery code that should add the array values to specific #id, buf it does not replace the code, only add more, and i need a little help to make it replace the html on othe link click.
Code:
function changeClass(curClass){
switch(curClass){
case "Schoolgirl":
case "Fighter":
var charSkillsNames = ["text1","text2","text4","text5"];
//loop show array values
listSkillsNames(charSkillsNames);
break;
}
}
function listSkillsNames(arr){
var length = arr.length,
element = null;
$("#skills").html(function(){
for (var i = 0; i < length; i++) {
element = arr[i];
$(this).append("<li>"+element+"</li>");
}
});
}
this works well but i need it to replace the html inside the "#skills" id when i click on the link that makes it work
PS: problem is really here
The issue is that you don't empty the HTML of #skills element. Use $("#skills").html("") to empty it.
function listSkillsNames(arr){
var length = arr.length,
element = null;
var $skills = $("#skills");
$skills.html(""); // empty the HTML
for (var i = 0; i < length; i++) {
element = arr[i];
$skills.append("<li>"+element+"</li>"); // append new items
}
}
The problem is because you are keep appending new items to the element always without removing the existing items.
Just empty the skill element, also there is no need to use the .html(function(){}) here
function listSkillsNames(arr) {
var length = arr.length,
element = null;
var $skill = $("#skills").empty();
for (var i = 0; i < length; i++) {
element = arr[i];
$skill.append("<li>" + element + "</li>");
}
}
What is the alternative way of doing something like
$(".myElement").each(function(){
//function
});
in plain Javascript?
This will iterate all divs in your current document. You can replace document.getElementsByClassName('someclass') etc. and do something with their attributes and values
var elements = document.getElementsByTagName('div');
for (var i = 0; i < elements.length; i++) {
doSomething(elements[i]);
}
Here is the jsfiddle: http://jsfiddle.net/allenski/p7w5btLa/
$(#myElement)
You are trying to iterate over a id selector. ID has to be unique in a HTML page.
If it's a class or element tags you want to iterate over you can use a for loop.
var $elems = $('.someClass');
for(var i=0; i< $elems.length; i++ ) {
// $elems[i] --> Gives you a `DOM` element
// $elems.eq(i) --> Gives you a `jQuery` object
}
Vanilla Javascript
var elems = document.getElementsByClassName('someClass');
for(var i=0;i< elems.length;i ++) {
elem[i] // Based on index
}
getElementsByTagName if you want to iterate over specific tags.
getElementsByName - get the elements based on name attribute.
You can also use document.querySelectorAll to get a list of objects and iterate over them.
var elems = document.querySelectorAll('.someClass')
for(var i=0; i<elems.length; i++) {
elems[i] // Give you DOM object
}
Alternative methods to the each function, here are two:
Setup
var $all = $('*');
var len = $all.length;
1
while(--len){
// use $($all[len]); for jQuery obj
var elem = $all[len];
doWork(elem);
}
2
//reset len for next loop
len = $all.length;
do {
var $elem = $all.filter(':eq('+ --len + ')');
doWork($elem);
} while (len);
var el = $(something);
for (var i = 0; i < el.length; i++) {
// do something with el[i] or more often with $(el[i])
}
el is a pseudo-array (or array-like Object) that has a length and elements accessible with the [] operator in the range 0...length-1. So you can do el[0], el[1] etc., but remember that el elements aren't jquery "objects", normally they are DOM elements, so you can't do el[0].text("Hello"). As in the each method, you have to do $(el[0]).text("Hello");
It's even wrong to do:
for (var i = 0; i < $(something).length; i++) {
// do something with el[i] or more often with $(el[i])
}
because in this way the $(something) will be recalculated every cycle.
You have to use a for loop. look at
http://www.w3schools.com/js/js_loop_for.asp
As you can see I am still a novice in javascript
Why is it so that you can append a Textnode only once? When you add it again somewhere else the first one disappears
I do not need a solution to a problem I was just curious what is causing this behavior.
Example where the textnode is only added to the last element of an array:
function hideAdd(){
var hide = document.createTextNode('Afbeelding verbergen');
var afb = collectionToArray(document.getElementsByTagName('img'));
afb.pop();
var divs = [];
for (i=0; i < afb.length; i++){
divs.push(afb[i].parentNode);
}
console.log(divs);
for ( i = 0; i < divs.length;i++){
divs[i].appendChild(hide);
}
}
This is where you use an unique textnode so it works:
function hideAdd(){
var hide = []
var afb = collectionToArray(document.getElementsByTagName('img'));
afb.pop();
var divs = [];
for (i=0; i < afb.length; i++){
divs.push(afb[i].parentNode);
hide[i] = document.createTextNode('Afbeelding verbergen');
}
console.log(divs);
for ( i = 0; i < divs.length;i++){
divs[i].appendChild(hide[i]);
}
}
Short answer is the DOM is a tree, not a network. Each node can have only one parent. If you could add a node in more than one location, it would have more than one parent.