When does the rendering update in JavaScript? - javascript

I was reading html specs concerning web api's , and it basically said that
After the event loop has performed some task from a task queue, it needs to update the rendering (if this is a window event loop)
It is also said that the user agent has some way of telling that updating the render isn't necessary (see point 10.3 "unnecessary rendering" in the link above)
So my question is the following: if, let's say, I have a simple index.html file and only one script file attached to it - index.js
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
Hello StackOverflow
<script src="./index.js"></script>
</body>
</html>
index.js
function add(a,b) {
console.log(a+b);
}
function modifyBackground() {
document.body.style = 'background : red';
}
console.log('Hello world'); // Task 1
add(4,5); // Task 2
modifyBackground(); // Task 3 Will the render be updated only here?
I view it that way - there are 3 tasks combined in my index.js. The first task is the console.log task,it is first added onto the task queue in the event loop.Then there's the add task, and finally the modifyBackground task.
In theory, if the user agent doesn't have a way of knowing if we actually need to update the render, it should update the render after every task.
Will the re-render happen only when I call the modifyBackground() method on the last line? And, if so, how does the user agent tell that the re-render isn't necessary?
P.S. If you want some clarification, I want to know, how does, for example, google chrome's user agent tell that the re-render isn't necesssary.

Will the re-render happen only when I call the modifyBackground()
method on the last line?
It depends on the browser implementation, they do not follow the specs sometimes.
And, if so, how does the user agent tell that the re-render isn't
necessary?
Again, it depends on the browser implementation. You need to understand how a browser rendering works. Here's a great explanation you can check it out: How the browser renders a Web Page. Below is a resume.
There are 3 basic concepts:
DOM
CSSOM
Render Tree.
Document Object Model (DOM)
When the browser reads HTML code, whenever it encounters an HTML element like html, body, div etc., it creates a JavaScript object called as Node. Eventually, all HTML elements will be converted to JavaScript objects. Since every different HTML element has different properties, the Node object will be created from different classes (constructor functions).
CSS Object Model (CSSOM)
After constructing the DOM, the browser reads CSS from all the sources (external, embedded, inline, user-agent, etc.) and construct a CSSOM. CSSOM stands for CSS Object Model which is a Tree Like structure just like DOM.
Each node in this tree contains CSS style information for that particular DOM element. CSSOM, however, does not contain DOM elements which can’t be printed on the screen like , , etc.
Render Tree
Here is the answer to your question. Render-Tree is a tree-like structure constructed by combining DOM and CSSOM trees. The browser has to calculate the layout of each visible element and paint them on the screen, for that browser uses Render-Tree. Hence, unless Render-Tree isn’t constructed, nothing will get printed on the screen.

Related

knockout and applyBindings - how to control the scope?

I am new to knockout, so going to fire a lot of questions. But I'm not new to data binding. So I am knocking my head on the difference between my expectations and reality. Here is a very basic question about applyBindings.
It looks like applyBindings has the parameter "view model", which is to me the domain object graph (as javascript objects) plus perhaps additional helper things added for the purpose of the view creation. But what I am completely missing at first is the scope of the bindings! I expected this to be applied to the current parent DOM element. But no, it is applied globally, in the entire page!
So is the expectation that in one HTML document there can only ever be one view model? This is very surprising to me! How am I supposed to create a single page web app where I have one panel showing the address book, another panel showing my appointments, another panel showing one loan application to review, and yet another showing the underwriting of another loan? They are all completely different things, am I really supposed to link them all into a single view model???
In my expectation, you bind a javascript object to a DOM element, and everything in there renders it. With every new nested DOM element, the focus object may change. It may be flowing out of some foreach binding from the parent's object. But then two sibling (or cousin) DOM elements might be sitting side by side and having completely different view model, and also a different life cycle. Like while I am in my underwriting workflow, I quickly need to bring up an address book or my calendar. All of it in a single page app. There should be no global interference between different view models used by different unrelated DOM elements.
And yet here we are with knockout I see it has only one ko.applyBindings(viewModelObject) for a the entire page.
What am I missing? What is preventing us from modifying ko.applyBindings to take two arguments, the view model-object and the DOM element in which to show it? I could try doing that, but I am afraid if knockout has been designed in this global mindset, there might be lots of issues running the knockout machinery more than once on the same page?
I'm sorry if I am frustrating people by shooting an answer already. But since I have a very urgent project I need to try to resolve my issues ASAP, and I am reading the knockout source code, which is quite nicely organized and uses good names, so it's quite intelligible; therefore I have found the answer myself.
The answer is that, yes, you can applyBindings to a parent element that you choose. The document.body is only the default if you don't say anything.
Therefore, from now on, I shall (tell my team to) always call applyBindings with the second argument specified for the rootNode. Like this:
<div>
... all my UI elements for this thing ...
... then last element in this div:
<script type="text/javascript">ko.applyBindings(viewModelObject, document.currentScript.parentElement);</script>
</div>
so, that way I can have multiple view models each in their own DOM element.
And additionally also, I was wondering, does knockout not somehow assign the model object to the DOM element? I could do that in my script tag too:
<div>
... all my UI elements for this thing ...
... then last element in this div:
<script type="text/javascript">
const viewElement = document.currentScript.parentElement;
viewElement.viewModelObject = viewModelObject;
ko.applyBindings(viewModelObject, viewElement);
</script>
</div>
and this allows me then -- if only for debugging -- to find the current view model object on the DOM element that is the root of a view. (It would be nice if that would happen with all other descendant bindings too, but that is perhaps the subject of another question.)
In fact, I decided to put into our general configuration a hard replacement of the ko.applyBindings function:
ko._applyBindings = ko.applyBindings;
ko.applyBindings(viewModelObject, rootNode, extendContextCallback) {
rootNode = rootNode || document.currentScript.parentElement;
rootNode.viewModelObject = viewModelObject;
ko._applyBindings(viewModelObject, rootNode, extendContextCallback);
}
now I don't even have to convince my team to do it this way, they will automatically, even without being aware of it.

How to understand and view parsing of HTML-embedded JavaScript?

I want to learn more about XSS, but I can't seem to find good resources on how HTML-embedded JavaScript, like the below code snippet, is parsed.
How can I view in the browser, how this code is parsed? I.e. how many rounds of parsing are performed, how each round transforms the input (e.g. decoding) etc.
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="setTimeout(() => alert(1), 1000)">Click this!</button>
</body>
</html>
After HTML parsing is performed, that decodes HTML encoded entites, what does the program look like? Does HTML parsing also mess with the onclick attribute?
Your question is fairly broad but seems to generally relate to how browsers render web pages.
Your browser requests the web document and begins interpreting it, reading line by line and building a Object Oriented representation of the Document Object Model (DOM); the DOM interfaces between javascript logic and the html document to dynamically construct the application.
When the browser reaches your button it renders the element with the written attributes; upon parsing the onclick attribute, it sets a event listener to the DOM for the click event and the event listener invokes the defined function asynchronously with the set parameters when the event is detected.
Please update your question if you require clarification on something specific or not addressed.

remove script after load in memory [duplicate]

As the title says, if I remove a script tag from the DOM using:
$('#scriptid').remove();
Does the javascript itself remain in memory or is it cleaned?
Or... am I completely misunderstanding the way in which browsers treat javascript? Which is quite possible.
For those interested in my reason for asking see below:
I am moving some common javascript interactions from static script files into dynamically generated ones in PHP. Which are loaded on demand when a user requires them.
The reason for doing this is in order to move the logic serverside and and run a small script, returned from the server, clientside. Rather than have a large script which contains a huge amount of logic, clientside.
This is a similar approach to what facebook does...
Facebook talks frontend javascript
If we take a simple dialog for instance. Rather than generating the html in javascript, appending it to the dom, then using jqueryUI's dialog widget to load it, I am now doing the following.
Ajax request is made to dialog.php
Server generates html and javascript that is specific to this dialog then encodes them as JSON
JSON is returned to client.
HTML is appended to the <body> then once this is rendered, the javascript is also appended into the DOM.
The javascript is executed automatically upon insertion and the dynamic dialog opens up.
Doing this has reduced the amount of javasript on my page dramatically however I am concerned about clean up of the inserted javascript.
Obviously once the dialog has been closed it is removed from the DOM using jQuery:
$('#dialog').remove();
The javascript is appended with an ID and I also remove this from the DOM via the same method.
However, as stated above, does using jQuery's .remove() actually clean out the javascript from memory or does it simple remove the <script> element from the DOM?
If so, is there any way to clean this up?
No. Once a script is loaded, the objects and functions it defines are kept in memory. Removing a script element does not remove the objects it defines. This is in contrast to CSS files, where removing the element does remove the styles it defines. That's because the new styles can easily be reflowed. Can you imagine how hard it would be to work out what a script tag created and how to remove it?
EDIT: However, if you have a file that defines myFunction, then you add another script that redefines myFunction to something else, the new value will be kept. You can remove the old script tag if you want to keep the DOM clean, but that's all removing it does.
EDIT2: The only real way to "clean up" functions that I can think of is to have a JS file that basically calls delete window.myFunction for every possible object and function your other script files may define. For obvious reasons, this is a really bad idea.
If your scripts have already executed removing the DOM elements are not going to get rid of them. Go to any page with JavaScript, open up your preferred javascript console and type $("script").remove(). Everything keeps running.
And this demonstrates #Kolink answer:
http://jsfiddle.net/X2mk8/2/
HTML:
<div id="output"></div>
<script id="yourDynamicGeneratedScript">
function test(n) {
$output = $("#output")
$output.append("test " + n + "<br/>")
}
test(1);
</script>
Javascript:
$("script").remove();
// or $("#yourDynamicGeneratedScript").remove();
test(2);
test(3);
test(4);
function test(n) {
$output = $("#output")
$output.append("REDEFINED! " + n + "<br/>")
}
test(5);
test(6);
test(7);

Serialization of the full page DOM. Can I get at the JS code that is loaded up, or must I AJAX it separately?

I have a bug I'm trying to track down, and it is very difficult to do so because of the complexity of the web app. There are many frames, and many instances of Javascript code that is embedded into the HTML in different ways.
The thing that needs to be fixed is a sub-page created with showModalDialog (so you already know it's going to be a disaster), and I am hoping that I can find a way to serialize as much of the DOM as possible within this dialog page context, so that I may open it to the same content both when the bug is present and when it is not, in hopes of detecting missing/extra/different Javascript, which would become apparent by pumping the result through a diff.
I tried jQuery(document).children().html(). This gets a little bit of the way there (it's able to serialize one of the outer <script> tags!) but does not include the contents of the iframe (most of the page content is about 3 iframe/frame levels deep).
I do have a custom script which I'm very glad I made, as it's able to walk down into the frame hierarchy recursively, so I imagine I can use .html() in conjunction with that to obtain my "serialization" which I can then do some manual checking to see if it matches up with what the web inspector tells me.
Perhaps there exists some flag I can give to html() to get it to recurse into the iframes/frames?
The real question, though, is about how to get a dump of all the JS code that is loaded in this particular page context. Because of the significant server-side component of this situation, javascript resources can be entirely dynamic and therefore should also be checked for differences. How would I go about (in JS on the client) extracting the raw contents of a <script src='path'> tag to place into the serialization? I can work around this by manually intercepting these resources but it would be nice if everything can go into one thing for use with the diff.
Is there no way to do this other than by separately re-requesting those JS resources (not from script tags) with ajax?

Algorithmic, Automagic Ajax

I have made a framework that generates a HTML "DOM" tree on the server, as a tree of python objects, and then spits it out as a string to be sent to the client. The way it does this is via a recursive depth-first traversal of the tree: for example a div would spit out the opening "div", spit out all it's children's html and then spit out the closing "/div".
This tree is broken down into conceptual components, as shown below:
graph http://lhy.mit.edu/media/Flow_Chart.png
This only shows the first two levels of hierarchy; the actual site has many more: for example each comment in the comment bar is a self contained component, each button on the menu bar is a self contained component. As you can see, the various components do not need to be on the same depth in the tree. What constitutes a "component" is decided by me.
What I want is the complete html string for each component (everything from the root node of that component downwards), as well as the partial HTML string for every component (The HTML of that component, minus the HTML of its children). The partial HTML of main section, for example, would be the html, head and two div tags only. The complete html of main section, on the other hand, would be every node on the page.
How would i do this? I could just find the complete HTML string of every component and sub-component, mark the boundaries of each sub-component with some string and do Regex-Removals in order to find the partial HTML string for every component, but that feels clunky and inefficient.
I could do an iterative-deepening DFS, halting at the boundary between a component and its sub-components until every node in that component has been explored. I would then have the partial HTML for every component but then i would need to do a similarly hacky Regex-Inserts to later build up the complete HTML for every component.
I could do both, but that would take two passes and would be expensive, though maybe not as expensive as the above Regex gymnastics.
I could do a priority-queue Dijkstra's, having each component be strictly higher priority than its children. It would traverse the tree in the correct order, finishing each component before moving on to its children, but i have no idea how i would get the final well-formed HTML string out of it.
The purpose of all this is so the server can intelligently and completely autonomously determine the minimal set of components on the client's page that need to change on a page-transition between two arbitrary pages.
If i create a new page on my site, I should need no more than Zero extra lines of code to have it ajax smoothly with any existing page.
But first i need to get my graph-traversing html-spewing algorithms in order. Any ideas?
I am presuming your client is Javscript code as you didn't specify anything.
Don't do anything too complicated. In particular, for the love of god don't try using regexes to work with HTML.
Is your server sending you a fully funciton HTML string? In this case, you can convert this into an actual DOM you can work with (there are many ways to do so) and then use the .innerHTML of an element to get your "complete html"s and use the .tagName to get a tag's name.
I still don't really get why you need all this complication. If you already went through the trouble of downloading the whole "new page" there isn't too much of a reason to try to change as few parts as possible - just replace averything and forget about it (the calls to the server should be the most expensive thing anyway).
If you really want to use less brute force, than you should find a way to request/be notified of only the interesting changes without having to look at everything. Then, given the part that is to be changed and the text, you just need to do something like
document.getElementById('mainCommentArea').innerHTML = newHTML;

Categories

Resources