Dynamically loaded elements are not in the HTML source code - javascript

I am fetching an attribute of a div from a page which loads the elements dynamically upon scrolling to the bottom of the page. There are 10 div's on the page initially and upon scrolling 10 new div's are loaded each time dynamically to the page.
My script looks like this:
var arr = document.getElementsByTagName('html')[0].innerHTML.match(/data-username="([^"]*")/gm); // I want the value from the attribute data-username
alert(arr.length); // size is 10
window.scrollTo(0, document.body.scrollHeight); // scroll to bottom to load 10 divs dynamically
arr = document.getElementsByTagName('html')[0].innerHTML.match(/data-username="([^"]*")/gm);
alert(arr.length); // size is still 10 but should be 20
Why is the array size still 10? How can I get all the 20 divs and iterate through them?
I took a look at the HTML source code and the problem is that the dynamically loaded div's are not there... How am I supposed to get the dynamically loaded elements?

I assume you are doing an ajax call to get the additional data, and you should wait for those elements to be available in the DOM (once it's complete) before doing things with them. That's quite easy with jQuery (as you had that as a tag)
http://api.jquery.com/load/
http://api.jquery.com/jQuery.ajax/

Related

How can I unload/load pages using jQuery?

Here is the things I want to achieve with jQuery.
First of all, I want to save a copy of the entire page as is in a variable.
I then want to replace the currently loaded page with a loading page from another html file or URL without redirecting to that page.
After it has done loading, I want to replace the page back with what it originally was (the variable from step 1).
The question asked
At it's simplest (and this is a gross simplification that will lose state like event handlers, iframe state, shadow DOM etc.) you "save a copy" of the page's HTML by using .html() on the root element (html or body for example).
You can replace the entire top level element with fixed content from another HTML file or URL by providing the data to the same .html(data) function as well.
You can restore the original content by repeating step 2 using the data you saved off in step 1.
// Step 1 - save old page
const oldPage = $('html').html();
// result of fetch() or fixed HTML from file
// const newHTML = ...
// Step 2 - load new page
$('html').html(newHTML);
// Step 3 - restore old page
$('html').html(oldPage);
What you might actually want
If you only care that the user can't see the old page, you may want to wrap all of the UI inside a div that you can set display property to none on. You could also just overlay the new UI elements on top of the old one, possibly wrapped in a container with a solid background (to prevent old UI elements from being shown through transparent background).

DOM element references are not being deleted when the element content is deleted using $(#aDIV).html("")

I have a container DIV on a page called "calgrid" that I fill with a calendar-style grid using AJAX. This allows me to update the calendar elements from the database every 60 seconds. The display is perfect and the updating is perfect. Here's my issue.
When I first load the page, I populate the grid locally with a DB call just to get the content on page. At that time, I can access elements within the grid using javascript and do things like highlight boxes with colors etc.
function findLocation(id,span,color) {
$("#"+id).css('width',(27*span)+'px');
$("#"+id).css('background-color',color);
}
This works fine on initial page load.
However, once the contents of that container DIV is reloaded using jquery "load" ajax call,
function setAjaxReload() {
if($('#override').attr('value') == 'yes') return;
$('#messages').css('background-color','#ffff00');
$('#messages').html('Contacting FileMaker');
$('#messages').css('visibility','visible');
$('#hopper').load('ajaxgrids.php','timebits=<?php echo $timebits; ?>&jobfilter=<?php echo $jobfilter; ?>&deptfilter=<?php echo $deptfilter; ?>&profile=<?php echo $profile; ?>&month=<?php echo $month; ?>&day=<?php echo $day; ?>&year=<?php echo $year; ?>',function() {
$('#messages').css('background-color','#00ff00');
$('#messages').html('Updating Schedule');
var blob = $('#hopper').html().split('^');
$('#details').html(blob[0]);
$('#wogrid').html(blob[1]);
$('#calgrid').html(blob[2]);
setTimeout(function() {
$('#messages').css('visibility','hidden');
}, 1000);
}
);
}
any attempt to access the elements within the container DIV by ID now fails. If I try to turn an element blue for example, the javascript executes but the cell doesn't turn.
Here's the strange part. If I add alarts to that javascript and first ask what is the cells current width and parent ID, the answers it returns are for the state of the original element created during page load, not the element that replaced it during the jquery load.
function findLocation(id,span,color) {
alert($("#"+id).css('width'));
$("#"+id).css('width',(27*span)+'px');
$("#"+id).css('background-color',color);
alert($("#"+id).parent().attr('id'));
}
It's as if the original content of the container DIV is still there someplace and new content has just been added to it, not replaced it. This is true even if I use $('#calgrid).html("") before the load just to make sure I kill it.
If I comment out the part of the load operation that updates calgrid and still update the other containers on the page, calgrid is completely blank on the page just as you would expect. However, even with no content, javascript can still access the properties of those supposedly removed element as if they are still in the DOM someplace.
I have inspected the DOM and there are no duplicate versions of the container DIV's children. Any idea how I can completely KILL the old elements each time I replace them through AJAX?

Hide div when array is empty

I have an array set up that has something added to the array every time to drop a word into a bucket on the page. I'm trying to show and hide certain div's depending on how many objects are in the array.
My code is:
if (test > 5){
$(".moving").hide();
$("#done").show();
}
This works perfectly except when the page first loads. The div with ID #done is still showing when the page first loads and then goes away when the array gets it's first object. (Array starts empty)
In your css just add #done{display: none;} That way the div will not show when page first loads.
Or use #done{visibility: hidden;} if you just want the div not to be visible.
If you don't have access to the HTML code you could hide it in ready function :
$(function(){
$("#done").hide();
//Or
$("#done").css("display","none");
//The rest of code
});
Hope this helps.
Use : #done{display:none;} or #done{opacity:0;}
Later in code, whenever you want to display it, you may use js/css to change display to block or opacity to 1.
The following function will hide done div and show moving div when page
is ready after complete page is rendered:
$(document).ready(function(){
$("#done").hide();
$(".moving").show();
});
Similarly you can use load method in to run a function on page load. but be aware load method is executed before complete page
is rendered
In your current code, you can add the following at the very beginning of ready function,
$('#done').hide();
or
$('#done').css('visibility','hidden');

Prevent DIV from scrolling on DOM content change

I am writing a document reading application using Node-Webkit. A document can be hundreds of pages long and the interface allows opening the document to a specific chapter. Once the initial chapter is displayed, I want to load the rest of the book asynchronously. Since I don't know what direction the reader will scroll, my strategy is to alternately load chapters before and then after the initial chapter:
load chapter x -> load chapter x-1 -> load chapter x+1 -> load x-2 -> load x+2 ...
I am displaying the book in a containing div element with each chapter being a div within the container. I'm using jquery .before() and .after() to insert each chapter as it is fetched.
My problem is that the browser automatically scrolls up when I add chapters earlier in the book. So if I start with chapter 10, the browser scrolls up when I add chapter 9 and again with chapter 8 and so forth.
One (unsatisfactory) solution to the problem is to make an anchor tag for each chapter and store the id of the first chapter loaded. Then after each chapter is fetched, runing the code:
window.location.href = #originalChapter
keeps the initial chapter in the browser viewport. Of course the problem with that is that the reader cannot scroll while the rest of the book is being loaded.
Ideally, I would like to disable scrolling, load a chapter and then re-enable until the next chapter is fetched. I'm so far unable to figure out how to do that.
If you're updating the DOM from the click handler of an anchor (<a/>) tag, make sure you return false from the callback function.
The simple solution in my mind would be to not have the elements in the DOM until they are loaded. The user won't be able to scroll because there won't be content to scroll to. Then, it's just a matter of preserving the viewport when the elements are added.
Take the initial position of your scroll container and the height of the overflow container:
var scrollTop = $scroll.scrollTop(),
height = $container.height();
and use them to preserve the viewport when you prepend new elements. You don't have to do anything when you're doing the append operation.
var newHeight = $container.height(),
newScrollTop = scrollTop + newHeight - height;
$scroll.scrollTop(newScrollTop);
Here's a quick example: http://jsfiddle.net/Wexcode/tfszaocz/

Run code BEFORE DOM loads

I have an HTML table with a time column, whose values I want to change. However, when I do this within the document.ready(), DOM manipulation heavily affects my load time.
Is it possible to change the table column cell values before the DOM loads?
The code I need to use for the manipulation is -
var time_col = rows[i].cells[TimeColumnIndex];
//Calculate new values
var time_Str = getUpdatedValue(time_col.innerText);
//Set values
time_col.innerText = time_Str;
time_col.innerHTML = time_Str;
I would appreciate any suggestions that people have, I'm still trying to understand things related to DOM, so please feel free to tell me if this cannot be done.
EDIT 1:
The getUpdatedValue() function just gets the difference in the users timezone as compared to UTC and adds the required number of minutes.
I've tried commenting out each line to see which lines actually increase the load time, and I found that it was just the DOM manipulation that took time, namely the following lines
time_col.innerText = time_Str;
time_col.innerHTML = time_Str;
My HTML table has about 1500 rows, so I go through each row and change the value of the time column.
If for some reason, you need your code to run immediately after the table has been loaded, you can just place your <script> tag immediately after the closing </table> tag
<table>
<tbody>
<tr><td>A</td><td>B</td></tr>
</tbody>
</table>
<script type="text/javascript">
var tables = document.getElementsByTagName("table");
var tableAbove = tables[tables.length - 1];
</script>
You cannot run code that operates on the DOM before the DOM has loaded. Hopefully, it obvious to you why that would be the case as DOM elements that aren't loaded are not accessible to javascript yet.
The options you have available are as follows:
Locate your script in your page immediately after the part of the DOM that you want to modify. Since things are loaded in pure sequence, you can manipulate any part of the DOM that is physically located before your script in the HTML file.
Use document.ready() for your code and just operate on the table after the whole DOM is loaded.
Hide the table initially with CSS so it is not initally visible. Modify it using either of the above two methods and then when you are done modifying it, show the table. This prevents the table being visible before you've modified it.
If an ajax call is involved in fetching the data for the table, you can further optimize things by starting that ajax call BEFORE the DOM is loaded and just store it's result when it completes (if the DOM isn't yet ready). This parallelizes the two operations so that the ajax call is being fetched at the same time as the DOM is loading. Then, when both the ajax call has completed and the DOM has loaded, you can then insert the ajax result into the DOM.

Categories