here i want to update demox element with all iteration of jsoDemo,but i only get final element in array.How do i arrange loop so that i update one by one ?
function GETJSON() {
for (var i = 0; i < jsoDemo.length; i++) {
var xxx = jsoDemo[i].name;
console.log(xxx);
}
return document.getElementById("demoX").innerHTML = xxx;
//break;
}
You are changing the innerHTML every time you go through the loop so when it finishes you only get the last one. You can either use document.getElementById("demoX").innerHTML += xxx; or if you want it to cycle through them use setInterval. Also, as the above answer states, put it inside the loop
Well, first, updating the DOM from within a loop is a big-time performance "no no" as successive changes to the DOM cause the user agent to rebuild the DOM each time.
Instead, build up a string in your loop and then set the final value of the string into your DOM element once the loop is done.
Also, .innerHTML is for when you are passing a string that contains HTML to an element's content and that causes that string to be parsed by the HTML parser. If you are not assigning a string that contains HTML, use .textContent instead to avoid that extra work.
Now, to your issue, you are using = when you should be using += to have each new value concatenated onto the last value. And, you don't need to return anything from this function, you only need it to update the element:
function GETJSON() {
var result = "";
for (var i = 0; i < jsoDemo.length; i++) {
result += jsoDemo[i].name;
}
document.getElementById("demoX").textContent = result;
}
Related
In one of my projects I just discovered, that sometimes iterating over an array of html elements (and change all of them) just affects the last element. When I log the element's attributes I can see that the loop definitily adresses every element but nevertheless visibly just the last element is getting changed.
Can anyone explain me why?
I already figured out, that a solution is to use createElement() and appendChild() instead of insertHTML. I just want to understand why javascript behaves like this.
Here is my example code:
/* creating 5 elements and storing them into an array */
var elementArray = [];
for(var n = 0;n<5;n++)
{
document.body.innerHTML += "<div id='elmt_"+n+"'>"+n+"</div>\n";
elementArray[n] = document.getElementById("elmt_"+n);
}
/* loop over these 5 elements */
for(var n = 0;n<5;n++)
{
console.log(elementArray[n].id); // logs: elmt_0 elmt_1 elmt_2 elmt_3 elmt_4
elementArray[n].innerHTML = "test"; // changes just the last element (elmt_4) to "test"
}
I created an example here: http://jsfiddle.net/qwe44m1o/1/
1 - Using console.log(elementArray[n]); in your second loop shows that innerHTML in this loop is modifying html inside your array, not in your document. That means that you are storing the div element in your array, not a shortcut to document.getElementById("elmt_"+n)
See the JSFiddle
2 - If you want to store a shortcut in order to target an element by ID, you have to add quotes for elementArray[n] = "document.getElementById('elmt_"+n+"')";, and use it with eval like this : eval(elementArray[n]).innerHTML = n+"-test";
See the JSFiddle for this try
I'm sorry if the title makes no sense. I am attempting to make a text input add strings to an array, which I then want to turn into a visual list. However, when using innerHTML to put the strings into a div, it prints the entire array rather than only the new string being added. Here is my code:
var nameList = [];
function addToList(frm) {
var list = document.getElementById("list");
if(frm.name.value !== "") {
nameList.push(frm.name.value);
} else {
alert("Not a name.");
};
for(var i=0, len=nameList.length; i<len; i++) {
list.innerHTML += "<div>"+nameList[i]+"</div>";
};
}
You can forgo your entire for loop. Everytime you've pushed a name, just add that name to the innerHTML. There is no need to iterate through your entire list everytime.
var nameList = [];
function addToList(frm) {
var list = document.getElementById("list");
if(frm.name.value !== "") {
nameList.push(frm.name.value);
list.innerHTML += "<div>"+frm.name.value+"</div>";
} else {
alert("Not a name.");
};
}
Note: I'm keeping your array assuming that it's used elsewhere outside of the provided snippet.
You're starting at the 0 array index each time you call the function, so it iterates the entire array every time it's called. If you want to only output the newest value when it's added, forget the loop and output frm.name.value each time the function is called.
If you're merely appending the new item to both the array and the HTML when the function is called, you don't need to loop through all items in the array and append them to the HTML; you can just add "<div"+frm.name.value+"</div>" to the HTML.
You'll only need to loop through all the array elements if there's a chance one of them has changed since the last time the function was called.
On an unrelated note, when you're just appending HTML to an element, you'll see a major performance improvement if you use element.insertAdjacentHTML("beforeend",yourHTML); instead of element.innerHTML += yourHTML;. Check out the jsperf test here to see for yourself!
I think your question is not so clear.
I think what you are trying to do is to have the values that have been input so far in an array and at the same time you want to show them on the screen right?
for(var i=0, len=nameList.length; i<len; i++) {
list.innerHTML += "<div>"+nameList[i]+"</div>";
};
The above code that you are running is not right. += is not valid here as it will add whetever html you have already rendered, which is not right.
list.innerHTML = "<div>"+nameList[i]+"</div>";
If you want to do in this way.
I have the following code in my application. It is supposed to build a comma separated string from a JQuery collection. The collection is retrieved from some xml. I use JQuery each() to iterate. This is standard code that I use all the time. I declare and define the result variable (patientConditions) first and set it to blank. Within the function I add the found string to the result variable along with a comma. I am not bothered by the trailing comma this leaves if there are results. The problem is that with no results the second line within my each() is running - they probably both are. After the loop has completed (with no matching elements in the xml) the value of the result is ','. It should be blank. I think this is something to do with closures, or hoisting, but I am unable to figure out how its happening. I have hacked a solution to this scenario, but am more worried about the hole in my js knowledge :(
var patientConditions = '';
$xml.find('patient>prescription>conditions').each(function() {
var conditionName = $(this).find('condition>name');
patientConditions += conditionName.text() + ',';
});
From what I can understand there is a match for patient>prescription>conditions, but not for condition>name, in that case $(this).find('condition>name') will return a zero elemet set. then .text() on that set will return a empty string
$xml.find('patient>prescription>conditions').each(function() {
var conditionName = $(this).find('condition>name');
if(conditionName.length){
patientConditions += conditionName.text() + ',';
}
});
Whenever a jQuery object is used to find non existant nodes, in this case $(this).find('condition>name'). The jQuery object still exists, it just contains no association to a node. This will allow you to run all jQuery functions on this object despite it not having any reference. This is why conditionName.text() returns an empty string despite no node being present. The solution, check if the node exists before doing anything.
var patientConditions = '';
$xml.find('patient>prescription>conditions').each(function() {
var conditionName = $(this).find('condition>name');
if (conditionName.length > 0) {
patientConditions += conditionName.text() + ',';
} else {
// Do something if node doesnt exist
}
});
I have a loop:
for (index = 0; index < total_groups; index += 1) {
groups[index].list_item = $(list_item_snippet);
// Closure to bind the index for event handling
(function (new_index) {
groups[index].list_item.find('.listing-group-title')
.html(groups[index].Group.Name)
.click(function(e){
fns.manageActiveGroup(new_index, groups);
return false;
});
})(index);
// Append to DOM
mkp.$group_listing.append(groups[index].list_item);
};
I would rather not call append() each time the loop fires.
I know that I could use a String and concatenate the markup with each loop iteration and append the string to mkp.$group_listing at the end, however this flattens the object and the bindings are lost (I am not relying on IDs).
Is there a way to perhaps add my objects to an array and append them all in one go at the bottom without flatening to HTML?
Assumptions:
$(list_item_snippet) contains some HTML defining a list item (and includes an element with class .listing-group-title).
groups is a block of JSON defining a 'group' in my script
The closure works perfectly
Edit:
Found that I can use the following syntax to append multiple elements:
mkp.$group_listing.append(groups[0].list_item, groups[1].list_item );
But i obviously need to automate it - it's not an array it's just optional additional function parameters so I'm not sure how to do this.
To append an array of elements to a selector you can use this:
$.fn.append.apply($sel, myArray);
In your case, since it's actually the .list_item property of each array element that you need you can use $.map to extract those first:
$.fn.append.apply(mkp.$group_listing, $.map(groups, function(value) {
return value.list_item;
}));
Instead of bind it the way you've done, if you bind it using on() like below,
$(document).on('click', '.listing-group-title', function() {
// click handler code here
});
You can flatten the HTML and append it in one statement and it'll still work.
Note: For better efficiency, replace document in the above statement to a selector matching the closest parent of .listing-group-title
Yes. Use the jQuery add method to add all your items to a jQuery object. Then append that one object.
http://api.jquery.com/add/
EDIT: Example:
var arr = $();
for (index = 0; index < total_groups; index += 1) {
groups[index].list_item = $(list_item_snippet);
// Closure to bind the index for event handling
(function (new_index) {
...
})(index);
// Add to jQuery object.
arr.add(groups[index].list_item));
};
mkp.$group_listing.append(arr);
I have a form that I want to only submit post data for value which have changed.
So the way I have been doing this is like this:
function submit_form(){
var hd = [];
// hd is a big array that is defined here
// hd ['some id_number'] = 'some value'
// main function
for (var id_number in hd ){
var x=document.getElementById(id_number).selectedIndex;
var y=document.getElementById(id_number).options;
selector_text = y[x].text;
if (hd[id_number] == selector_text){
$(id_number).remove();
}
}
document.forms["my_form"].submit()
}
So the goal is that if the selector equals what is in the array, then don't POST the data.
To do this I have been doing the remove function. Everything up to the remove function works as expected. However when I look at the post data I still get the selected value for the id_numbers that mach the value in hd.
Is there a better way to remove to prevent it from going to the POST data? The id.parent.removeChild(id) method didn't work either.
The jQuery id selector should begin with a #, but yours appears not to:
$('#' + id_number).remove();
Your for-in loop should be a regular incremental for loop, which is the proper way to iterate an array in JavaScript. for-in loops are typically used for iterating object properties rather than array elements.
for (var i=0; i<hd.length; i++) {
// Access hd[i] in the loop
var x=document.getElementById(hd[i]).selectedIndex;
var y=document.getElementById(hd[i]).options;
selector_text = y[x].text;
if (hd[i] == selector_text){
$('#' + hd[i]).remove();
}
}
Since you aren't really using jQuery here except for that line, instead the plain JS version is:
var removeMe = document.getElementById(hd[i]);
removeMe.parentNode.removeChild(removeMe);