I am studying the basic internal functionality of the JavaScript TurboLinks framework at the moment. From what I understand, onclick events are assigned to all anchor tags to be able to prevent the default action (full page reload) and load the link content via AJAX instead. Please correct me if I am wrong here.
When the AJAX callback receives the whole HTML document as a string, how can it be rendered without (re)loading script and style tags?
Scripts and styles will only be (re)loaded and evaluated when they are inserted into a page. When the HTML is received via AJAX, Turbolinks creates a new HTML document behind-the-scenes, and sets its content to the HTML response. As this is not yet rendered/inserted, the browser does not download/evaluate any scripts or styles. The <head> of the new document can now be compared to the current one and additional assets can be added as necessary.
In terms of the specific Turbolinks components:
Visits create Snapshots from the AJAX response (see Visit#loadResponse)
Snapshots create HTML elements behind-the-scenes (see Snapshot#fromHTMLString
SnapshotRenderers handle merging the <head> and replacing the <body> (SnapshotRenderer#mergeHead and SnapshotRenderer#replaceBody)
Related
I have an issue with dynamically loaded content.
I'm using ajax calls to load in HTML content without refresh the browser, and pages have their own JavaScript libraries that need to load in order for them to work. So I embed that JavaScript content into the HTML which I load with ajax.
The problem is, that even though the HTML that had the embeded JavaScript gets removed, the functionality of those JavaScript functions is still loaded no matter if the HTML along with the JavaScript is removed.
That means, that if a certain page is loaded more than once, actions will fire the same amount of times that the pages has been loaded.
How do I make sure that JavaScript libraries get only loaded into the browser once, retaining the functionality of loading the source of the JS libraries with the ajax call, not just having source file links and then loading them again after the ajax call along with the required HTML is loaded? (load the JS files along with/before the HTML is loaded with ajax)
Once you load a JavaScript file into your browser's memory, it remains there until you load another page.
So... it doesn't matter how do you load it (through AJAX, or just once when page load through script link, or just embedding it into your raw HTML), once it's there it will remain there until you go to another page.
If you want your client code to execute only under certain circumstances you need to control that.
From my point of view your best option is to just load once your libraries and determine by code when execution should start, end, and repeat (if needed).
First question:
About Dynamic Script Elements
var script = document.createElement ("script");
script.type = "text/javascript";
script.src = "script.js"; document.getElementsByTagName_r("head")[0].appendChild(script);
The important thing about this technique is that the file is downloaded and executed without blocking other page processes, regardless of where the download is initiated. You can even place this code in the <head> of a document without affecting the rest of the page.
I want to know what is difference between Dynamic Script Elements and this codes
<script type="text/javascript" src="script.js"></script>
Why does Dynamic Script Elements download and execute file without blocking other page processes and the other will?
Second question:
I know that the page download and rendering must stop and wait for the script to complete before proceeding, so I put scripts at the bottom before </body>
Is it necessary to use XMLHttpRequest Script Injection or other libraries like lazyload when I put scripts at the bottom, and why?
Anybody know this? Thanks
I want to know what is difference between Dynamic Script Elements and
this codes
Your code snippet is a dynamic script element. It is added dynamically to the page and is not natively present in the HTML of the page.
Script tags present in the HTML of the page are executed sequentially as the browser encounters them during the parsing of the page. The first script element is executed before any others, then the second and so on. Because there can be script elements embedded anywhere in the HTML of the page and they must execute in sequential order, a script element in the page must load and be executed before the rest of the HTML after it can be parsed and added to the page.
Why does Dynamic Script Elements download and execute file without
blocking other page processes and the other will?
I'm not sure what kind of answer you're looking for here. It works this way because this is how the designers of the browser/HTML specs decided it would work. A dynamically added script executes asynchronously, independent of the loading of the page. A script element present in the HTML of the page executes in a predictable order with respect to both other scripts and with respect to the loading of the page elements. This can be very important for some types of scripts (such as document.write() and thus the designers of these specs allow you to have either predictable, sequential order (which by its very nature must block until complete) or asynchronous loading. The defer and async attributes also allow you to change the behavior of even script tags that are present in the HTML of the page. So, this way you can have whichever behavior is most advantageous.
Is it necessary to use XMLHttpRequest Script Injection or other
libraries like lazyload when I put scripts at the bottom, and why?
No, it is not necessary to use script injection. Putting a script at the bottom of the page will allow the page elements above it to show to the user without waiting for the script to execute (if that is your goal). There are many other reasons for dynamically loading scripts besides just page load performance. For example, some scripts are loaded only when needed based on what action the page is going to execute.
For a lot more info about the execution order of scripts including the effect of the defer and async attributes in script tags, see this detailed post: load and execute order of scripts
The position of the script tags has something historical. In the early easy was often document.write() used to the Dom could change that is why a script block can block the rendering. However there is a attribute which says I don't change the Dom go on.
Script tags at the end of the page are related to the time when the download process is triggered so this can optimize the load process.
That lazyload libs are helpful of you need some other frameworks/libs only under some runtime conditions. It's all about page load times and how fast the page react on user interactions.
I'm noticing something strange when using the jQuery ready event in Rails. If the handler is added in the <head> section, either directly within script tags or in asset pipeline files included using <%= javascript_include_tag ..., it will only execute on the first page request, and not on subsequent requests. That is, explicit browser actions to load/refresh a page will execute it, but new page views triggered from clicking around on links will not.
On the other hand, if it's included in the <body>, it will fire every time on every page view- like you'd expect.
<head>
<script>
jQuery(document).ready(function(){
console.log('READY in head'); // Fires on first page load only
});
</script>
</head>
<body>
<script>
jQuery(document).ready(function(){
console.log('READY in body'); // Fires every time
});
</script>
</body>
Really confused. I'm seeing it in all my Rails apps, but don't understand how Rails could effect this as jQuery is a client-side technology??
from RailsApps Project :
The Rails asset pipeline will become even more important in Rails 4.0
with the new Turbolinks feature. Turbolinks improves performance by
keeping the current page instance alive and replacing only the page
BODY (plus the title in the HEAD). As long as the HEAD element is
identical between pages, the Turbolinks mechanism can deliver its
“turbo” speed boost. This adds to the importance of avoiding any extra
script tags on specific pages.
Using AJAX (or turbolinks) as you said would not actually load a new page, but insert it into the dom. Therefore the ready event would not fire. :)
I'm modding a web page that's generated by a third party project. The project essentially does something like this when your browser requests a page (pseudocode):
<?php
include: project's fixed library INCLUDE's
include: my freeform php code
?>
(project's fixed HTML <head>...</head> and <scripts/> sections)
(project's fixed HTML <body> tag and page header + frames)
(my freeform php/HTML code)
(project's fixed HTML footer, frame closures, and </body> tag)
The page contains form elements and HTML that's generated and filled in by php based on $_GET/$_POST. My HTML contains "OnChange=ValidateItems();" for most fields; when the user changes data on the page, error messages will appear inline if relevant.
What I want is to also trigger "ValidateItems();" after the page loads, when the initial user-provided values are set up in the HTML ready for the user. But I don't have access to usual or placements due to the above loading structure. I'm wondering how else to make it happen.
One option I was thinking was to add a tiny invisible frame/frameset/iframe or other object that does support onload and isn't reliant on the or tags, and 'bootstrap' myself from an onload= call of that, to then manually add onload to the body, or hook the usual onload event somehow, in order to call ValidateItems() once at the right time, then exit the snippet once it's set up or done. I have no idea what the best way to do this - how I'd initially get any code to execute, what I'd then hook or modify etc so it happens appropriately (not too early or late); this is leagues past me technically. Help and example code would be very much appreciated.
Add this somewhere inside your 'freeform html' code:
<script>
window.onload = ValidateItems;
<script>
When a jsp page includes jsp dynamic includes...
<jsp:include page=”filename.jsp” />
...is it possible that the document onload event (or prototype's dom:loaded event) could get fired too early? (i.e. before the included filename.jsp has fully loaded)
The reason I suspect this may be the case is that the included file is compiled separately and only included by directive at runtime. The parent jsp might assume that loading of the directive itself is sufficient to consider the DOM is loaded - the includes page is loaded asynchronously and its loading is might not be monitored by the document.
Is this a valid concern?
Thanks in advance
This is included serverside, not clientside. It's certainly not asynchronously. The client receives one response. Rightclick page and view source. It's all plain HTML.
If you have problems with onload, it lies somewhere else. Verify/validate the generated HTML output.