Inserting DOM element while page is loading, not afterwards - javascript

I am working on a chrome extension, that inserts a div into the body element of the dom. Right now I am creating an event handler that fires on load to create the element. This means of course that the page loads completely, and then my div is inserted, which means the user sees the page without the div until loading is complete, and then the div pops up. I would like the div to be there while the page is loading. Is there a way to hijack the body element before any other elements have been written? Or do I have to somehow hide the content until everything has loaded, which of course would mean that the user sees a blank screen for a while.
If at all possible, I would like to avoid jQuery.

I'm not 100% sure, but looking at the Chrome extension developer guide, it looks like if you are using a Content Script and specify the run_at field in your extension's manifest as document_start, then it should inject the files before the DOM is constructed.

Related

Insert iframe at chrome.tabs.onActivated

I want to insert an iframe when chrome.tabs.onActivated gets triggered when going to already opened tabs.
I'm developing an extension that does the chrome.scripting.executeScript on all tabs in the browser at initialization.
I'm registering message listeners on the content script and the background.
From the popup extension, I'm clicking a button that tells the content script to insert an iframe.
On the current page it works. If I open a new page it works. But when I'm going to an existent tab, nothing happens in the content scripts.
In the background the console logs are showing I'm on the correct tab. Only if I refresh the existent open tab, the iframe is inserted.
I've tried injecting the scripts again at onActivated, but nothing happens.
What is the correct way of doing this?
Later edit:
It seems that I had a faulty condition in my chrome.scripting.executeScript and the scripts were never programatically inserted. They were inserted from the manifest.json
I don't need to insert the scripts again on onActivated, as they are inserted by executeScript.

jQuery cannot detect an injected script that updates the page

I'm trying to use jQuery to modify an element that's "injected" externally. I've tried delegation with on but it didn't work.
Here's the page, scroll down and you'll see an avatar named "Sebastian" with <div class="Avatar">.
If I go right click, Console and type: $('.Avatar'), the element is identified, but this is only because I first clicked on "Inspect element" for that element. jQuery somehow "updated" the source and now it identifies the element.
Now, try to refresh the page and type $('.Avatar') again, jQuery will not identify the element (although it's already loaded on the page).
You can take a look under "A working example" how this script is injected into the page.
My question is, is it possible (and if so, how) to modify this HTML (which seems to be inserted dynamically as the page is loaded)? It doesn't seem to be using any sort of iFrame nor anything, it just dynamically loads into the page, yet jQuery is unable to recognize it (unless you "tell it" to do so by clicking on "Inspect element" on the actual element).
P.S. I've tried using on, delegate, it doesn't work.
jQuery will not identify the element after page because it's in another iframe.
You said "It doesn't seem to be using any sort of iFrame nor anything", but in the end it's iframe.
The reason why you can find it when you go right click on element and then in developers tools you write $('.Avatar') is because once you inspect element (right click) inside developer tool iframe will change.
Furthermore, your parent iframe and iframe that have avatar element have same origin. Run document.domain inside parent and other iframe. Iframe with avatar have origin "app.talkjs.com" and parent iframe have origin"talkjs.com".
Subdomains may be same-origin.
There’s a small exclusion in the “Same Origin” policy.
If windows share the same second-level domain, for instance john.site.com, peter.site.com and site.com (so that their common second-level domain is site.com), they can be treated as coming from the “same origin”.
https://javascript.info/cross-window-communication
You should be able to catch onload iframe event and then search for .avatar.
iframe.onload = function() {
let newDoc = iframe.contentDocument;
console.log(newDoc.getElementsByClassName("avatar");
};

How to run Greasemonkey/Tampermonkey userscript repeatedly inside of iframe after full page load?

I'm trying to write a userscript working on the Etherpad page whose content will be updated continuously. The relevant part of the page structure is on the screen:
My userscript should affect all the div entries under 'td id="sidedivinner"' element. However, this element does not exist on the page initially and it is built only after the content of both iframes on the screen loads. All the solutions I found on the problem "Execute userscript after page load" failed, because they assumed either that there are no iframes, which still load after the script, or that iframe has the unique name or id.
So basically I want to execute js after all iframes load, as if I had done this via web browser console.
Also I want to run the same script after every AJAX request affecting sidedivinner (It will be too expensive to run it after every AJAX request). I suspect this solution won't work using #sidedivinner id because "waitForKeyElements.js" won't recognize an element by Id inside the iframe. How can I do this?
Add your javascript to the onload event of the iframe - not the page.
iFrame onload JavaScript event
You could use jquery to check for the creation of the #sidedivinner object. The following jquery will search in any iframes on the page.
$("iframe").contents().find("#sidedivinner")
See the following for more on these jquery functions:
https://api.jquery.com/contents/
https://api.jquery.com/find/

How do I get my chrome extension to inject its iFrame adjacent to, rather than on top of the existing page

I am writing a Chrome Extension that injects itself into an iFrame that is appended to the BODY of the host page. However this iFrame appears above the existing page content, not adjacent to it.
I've tried appending the iFrame directly to the HTML element instead of the BODY but that doesn't appear to make any difference.
How do I inject it such that the iFrame pushes the host page content over, so all of that content is still accessible by the user?

When do you choose to load your javascript at the bottom of the page instead of the top?

I have seen JavaScript libraries being loaded at the top and bottom of the page.
I would love to know when to make these choices. All the JavaScript code I've written all work at the top of the page, which includes jquery plugins.
When do i load my script at any of these positions?
Top: When having JavaScript events function on elements immediately is more important (so if you use a DOM Ready event to load everything, this is the wrong place)
Bottom: When loading the content is more important
Yahoo says to Put Scripts at the Bottom. Google says something similar but not as clearly.
The reason you do it at the bottom of the page is because if you put it at the top of your page then the rendering of your page will wait for these files before it renders. This is why a lot of people put JavaScript at the bottom of the page as it allows the entire page to be rendered then the JavaScript is loaded.
There's very rarely any reason you'd want to put the JavaScript at the top of the page, and unless you have an explicit reason you want the JavaScript loaded in before the main page then put it at the bottom. Most optimization guides suggest putting it at the bottom for this reason.
I place all CSS in the HEAD to avoid excessive screen paintings and flashes of style.
I place most JavaScript file requests at the bottom of the page so that the page can render quickly (HTML/CSS loading will block until script tags above them have been loaded and processed). Any code that needs to be executed after the library files have loaded are executed onDOMReady, which is all code except for library initialization. I pretty much followed Google's PageSpeed recommendations.
I've been thinking about using LABjs as well to further decrease page load times, but this works well enough right now.
When the browser encounters a script element it has to evalute the JavaScript contained in that element because the script might alter the content of the page (via document.write) or inspect the current state of the page.
If the script element loads script using the src attribute, loading of other resources (JavaScript, CSS, images, etc.) will be blocked until the current script is loaded.
Both of these factors can slow down the perceived load time of your page.
If your JavaScript does not alter the page or if it doesn't need to inspect the state of the page until it has loaded you can mark your script element with defer="defer" (supported by IE 6+ and Firefox 3.5+) which indicates that the evaluation of the script can happen "later". Moving your script elements to the bottom of the page effectively does the same thing - since your scripts appear at the end of the document they'll be evaluated after CSS, images, etc. are loaded and the HTML is rendered.
Because of the fact that browsers have to pause displaying content of a page when it's parsing a Javascript file, the recommendation is to load the Javascript at the bottom of the page to speed up displaying a page's content. This works best if your website can be rendered without any Javascript executing to modify the page because the page will be available for user interaction even if a script hangs for longer than expected.
I put all external scripts (such as Google analytics) at the bottom so their lag does not effect the loading of the DOM.
Simply put, if your script have snippets that would start executing right away (outside all function(){} bodies) and that access DOM elements, it should go at the end of the page so that DOM would have been built and be ready to be accessed by the time the script starts executing.
If you are accessing DOM only from function calls (like onload, onclick etc), you can put the script safely in the head section itself.
I put a small script in the head that does anything I want done before the rest of the page renders, and loads any other required scripts onload, or as needed after the document loads.

Categories