Loss of array elements after putting .innerHTML = "" - javascript

In my HTML I have a content div that contains articles created by a php script and handled with JQuery and Javascript. With Javascript I collect those articles into an array with the 'getElementsByClassName' function.
The scripts and HTML I'm writing here are simplified. I need this array because I'm trying to make that if the length of the array is larger than 10, only 10 articles are displayed per page. So page 1 will be index 0 to 9 of the array, page 2 index 10 to 19, etc.
Now,
Take this html code.
<body>
<div id="content">
<div class="article">
<p>Article 1</p>
</div>
<div class="article">
<p>Article 2</p>
</div>
<div class="article">
<p>Article 3</p>
</div>
</content>
</body>
And this Javascript code.
$.post("getarticles.php",{ page:"home" } ,function(data){
//place the content
document.getElementById("content").innerHTML = jQuery.trim(data);
//put elements in array
arrArticles = document.getElementsByClassName("article");
alert(arrArticles.length);
document.getElementById("content").innerHTML = "";
alert(arrArticles.length);
})
The first alert gives me "3", which is correct.. But the second alert gives me "0". Why is the array losing it's elements after the elements have been put in it?
By the way, the 'data' variable is a string of HTML passed on by a php script.
For example: In the php script I have the code
echo "<div class="article"><p>Article 1</p></div><div class="article"><p>Article 2</p></div><div class="article"><p>Article 3</p></div>"
&
document.getElementById("contentWrap").innerHTML = "";
I know this is causing the problem, but I don't know why. Can anyone explain or provide an alternative?
Thanks in advance

getElementsByClassName() returns a dynamic array (actually a live NodeList) that will change dynamically if/when you modify the DOM. So, if you change the content with innerHTML and elements in that array are affected, the array will change automatically.
If you want to keep this list of elements and make it not be live (so it won't change when the DOM is changed), you can make a copy of the NodeList into a normal array (that is not dynamic) and once it is in a normal array, the references to the DOM elements will keep them from getting destroyed. It won't prevent them from getting changed if your code changes their contents, but it will keep them around even if your code caused them to get removed from the DOM.
One way to make a copy of the dynamic NodeList into a static array is like this:
// fetch dynamic NodeList
var items = document.getElementsByClassName("article");
// make static copy of NodeList into normal array
items = Array.prototype.slice.call(items);
Or, since your post is tagged with jQuery, you can just use jQuery in the first place which contains a static array of nodes that isn't affected by other changes in the DOM:
var items = $(".article");

It looks like document.getElementByClassName is returning a reference to the element array which is being updated when you change the mark up. Not sure why; perhaps somebody better informed than me can answer that.
Using jQuery to select the array worked for me:
var arrArticles = $(".article")

document.getElementsByClassName("article");
return [NodeList array], this array contain pointers to DOM elements
arrArticles = anotherArray;
this code do not create a copy of anotherArray, but it is make a pointer to values form anotherArray.
So when elements in anotherArray will be deleted, in arrArticles elements will dissapear also.

Related

not able to change class within id although no errors

I don't understand why my extraInfo variable isn't being printed out onto the webpage.
The information is being retrieved correctly (I've tested this with alert()) but I just cannot figure out why it isn't replacing the span text with the returned value.
I've tried sending it out wrapped in P tags too and although no errors come out, it still doesn't amend the text.
https://github.com/ralam87/Quote-generator
Where am I going wrong?
document.getElementById("source").getElementsByClassName("citation")[0] = extraInfo;
I gone through your example.
Note: when you are trying to assign the citation to first element with .citation class that time the there are no elements present with the class citation because it get replaced when you set the value to source element just before citation document.getElementById("source").innerHTML = author;.
This are possible solution
change this document.getElementById("source").getElementsByClassName("citation")[0] = extraInfo; to document.getElementsByClassName("citation")[0].innerHtml = extraInfo;
remove the id from <p id="source">
create another <span> or <div> or <p> element inside the existing <p> and assign the id=source to that inner element. for example <p><span id="source"></span><span id="citation"></span></p>.
If you want to have the , after the source name then at the time of assigning the document.getElementById("source").innerHTML = author + ',';.
If you allow me i can also contribute this directly to you git
repository.

jQuery -Wildcard Selector Starts w/String and ends w/Variable

I've been looking all over the web for an example or solution, but have not been successful yet. The challenge I am facing is using jQuery to select an element ID that starts with a string, but also ends with a variable passed in by a function.
Example:
.JSP file - There is a ForEach loop that creates dynamic divs and adds a variable ${number} to their 'id' as a key. This allows a button to show/hide only that unique div without impacting other divs on the same page.
<div id="success-icon${number}"></div>
<div id="success-msg${number}"><p>My Message</p></div>
<button id="success-btn${number}" onclick="showIcon(${number})">Show Button ${number}</button>
.JS file
//does not work, because it is looking for success+number
function showIcon(number){
$('[id^=success]'+number).show();
}
I need it to look for an id that starts with "success" and ends with "number" variable.
Would really appreciate any help on this and thanks in advance for your time!
You can use as selector:
$('[id^=success][id$='+number+']').show();
But beware, would match for number = 1; both divs with IDs: success-icon1 and e.g success-icon11. Now that's depend your expected behaviour.
Anyway, to 'group' some elements, you would have better to use a common class specific to each grouped element.

jQuery extracting data using filter

I'm trying to get content inside a div in another pages.
$.get('page1.php', function(data){
//option 1 <-- Cannot get content in a div inside a div, but can get root-div content
var content = $(data).filter('#bar').html();
//option 2 <-- Cannot get root-div content, but can get content in a div inside a div
var content = $('#bar', data).html();
});
I have noticed a problem, if I use filter function to extract data, I will not be able to get the content of a div inside a root-div. For example to get the content in id bar with this code: $(data).filter('#bar').html();
<div id="foo">
<div id="bar">
Lorem ipsum
</div>
</div>
However, If i use $('#bar', data).html(), I can retrieve the content inside bar, BUT I can't retrieve the content of foo for example ('#foo', data).html().
Are there any functions where you can combined these 2 situations instead of using these 2 methods together?
You should give an example with data specified, to make it clear what behavior you're expecting.From what you wrote, I'm supposing you're trying to use filter to select from the children of a div. It won't work, because filter selects from the objects in the current selection, it doesn't care
what is inside those objects. So, if you have div#foo in your selection, it won't care about div#bar inside it.
So, this works:
$("#foo").filter("#foo").html()
But it won't work
$("#foo").filter("#bar").html()
because div#bar is not in the selection from which you're trying to filter. It could work this way:
$("#foo").children().filter("#bar").html()
In case I misunderstood your question, I apologise, and will gladly update my answer.

Whats make different in below Jquery code?

I'm working with on developing one of the social networking site and its having some notification features in left panel.
Whenever any user have played a game it will automatically change the number of notification count.
For that i have using below code line.
jQuery('#count_id').load('mypage.php');
But it will retrieve me whole site content with header,footer and content area in the response text, which is wrong as per my requirements.
but if i used below code of line
jQuery('#count_id').load('mypage.php #count_id');
then it will retrieve me a real count but add another div in between the original,
Original html:
<div id="count_id" class="notify">2</div>
and Code after retrieving response:
<div id="count_id" class="notify">
<div id="count_id" class="notify">1</div>
</div>
which is also not as expected. count are right but i don't want to add new div inside a original one.
What should i need to change in my code?
Thanks.
jQuery('#count_id').load('mypage.php #count_id > *');
That would bring only the DOM childs (the content)
Because this is how it works. Also it enables you to attach events to the element you load and delegate them inside this element (so new elements can also benefit from attached JavaScript events) - see .delegate().
If you want to replace the element, you can try the following:
jQuery.get('mypage.php', function(data){
jQuery('#count_id').replace(jQuery(data).find('#count_id'));
}, 'html');
I did not test it, but it should work.
Ivan Castellanos is however right. According to the documentation, you can provide any selector after the first space in the .load()'s parameter.
To retrieve count_id, you can directly get the html value in the div like this:
<script type='text/javascript'>
jQuery(document).ready(function()
{
countVal = $("#count_id").html(); //returns the html content inside the div, which is the count value
countVal = parseInt(countVal); //This will convert the string to type integer
});
</script>
Note:
If you want increase the count and update the div value, you can add the following lines:
countVal++;
$("#count_id").html(countVal);

javascript innerHTML without childNodes?

im having a firefox issue where i dont see the wood for the trees
using ajax i get html source from a php script
this html code contains a tag and within the tbody some more tr/td's
now i want to append this tbody plaincode to an existing table. but there is one more condition: the table is part of a form and thus contains checkboxe's and drop down's. if i would use table.innerHTML += content; firefox reloads the table and reset's all elements within it which isnt very userfriendly as id like to have
what i have is this
// content equals transport.responseText from ajax request
function appendToTable(content){
var wrapper = document.createElement('table');
wrapper.innerHTML = content;
wrapper.setAttribute('id', 'wrappid');
wrapper.style.display = 'none';
document.body.appendChild(wrapper);
// get the parsed element - well it should be
wrapper = document.getElementById('wrappid');
// the destination table
table = document.getElementById('tableid');
// firebug prints a table element - seems right
console.log(wrapper);
// firebug prints the content ive inserted - seems right
console.log(wrapper.innerHTML);
var i = 0;
// childNodes is iterated 2 times, both are textnode's
// the second one seems to be a simple '\n'
for(i=0;i<wrapper.childNodes.length;i++){
// firebug prints 'undefined' - wth!??
console.log(wrapper.childNodes[i].innerHTML);
// firebug prints a textnode element - <TextNode textContent=" ">
console.log(wrapper.childNodes[i]);
table.appendChild(wrapper.childNodes[i]);
}
// WEIRD: firebug has no problems showing the 'wrappid' table and its contents in the html view - which seems there are the elements i want and not textelements
}
either this is so trivial that i dont see the problem OR
its a corner case and i hope someone here has that much of expirience to give an advice on this - anyone can imagine why i get textnodes and not the finally parsed dom elements i expect?
btw: btw i cant give a full example cause i cant write a smaller non working piece of code
its one of those bugs that occure in the wild and not in my testset
thx all
You are probably running into a Firefox quirk of following the W3C spec. In the spec the whitespace between tags are "text" nodes instead of elements. These TextNodes are returned in childNodes. This other answer describes a workaround. Also Using something like JQuery makes this much easier.
I would expect this behavior in any browser as the += operand overwrites what is already in the table by definition. Two solutions:
Instead of receiving HTML code from your PHP file, have the PHP generate a list of items to add to the table. Comma/tab separated, whatever. Then use Table.addRow(), Row.addCell() and cell.innerHTML to add the items to the table. This is the way I would suggest doing it, no point in creating GUI elements in two separate files.
The other solution is to save all the form data that's already been entered to local JavaScript variables, append the table, and then reload the data into the form fields.
Well, returning a JSON object with the new data seems like the best option. Then, you can synthesize the extra table elements by using it.
In case one is forced to get plain HTML as response, it is possible to use var foo = document.createElement('div');, for example, and then do foo.innerHTML = responseText;. This creates an element that is not appended to anything, yet hosts the parsed HTML response.
Then, you can drill down the foo element, get the elements that you need and append them to the table in a DOM-friendly fashion.
Edit:
Well, I think I see your point now.
wrapper is a table element itself. The nodes reside under the tbody, a child of wrapper which is its lastChild (or you can access it via its tBodies[0] member, in Firefox).
Then, using the tBody element, I think that you would be able to get what you want.
BTW, You do not need to append the wrapper to the document before appending its children to the table, so no need to hide it etc.

Categories