Based on the code below, I would like to know if there would be a significant change in the page loading time if i would to call the desktopPopup html scripts later (assuming I have alot of html codes which are being executed there) or am I doing it just wrong? The comparison is using the method below and against writing the entire html code without the scripts
<script id="desktop" type="text/html">
//some html in here
</script>
<script type="text/javascript">
$(function() {
$('body').one("click", function(e) {
$("body").append($('#desktop').html());
});
});
</script>
Including it right away will be faster. In this case your browsers only needs to build DOM and render it.
In the second case your browser has to:
download and execute jQuery (if it hasn't been done beforehand)
select elements from DOM, insert HTML into it
rebuild part of DOM and render it
Related
What I need is to hook/intercept other external JS load.
I can place js anywhere in document
Example:
<script src="hook.js"></script>
<script src="a.js"></script>
<script src="b.js"></script>
Hook.js should intercept a.js and b.js. Problem is, that when hook.js is executed, i cannot see other scripts (document.scripts contains only hook.js) and document ready event is too late (scripts a.js and b.js are executed).
Is there any way to "see" other script tags, before are executed ?
Thanks for any help
Edit
I need to do any "magic" inside hook.js without modyfing (statically) other HTML.
No jQuery
Credit goes here: https://stackoverflow.com/a/59424277/2016831
You can use a MutationObserver to see what elements are being added to the DOM, and when they are being added, simply change the source code, or if its referencing another URL, just redirect it to your own server, with the original URL as a get parameter instead, and return the modified code that way.
Based on the above answer, you could do something like this:
<script>
new MutationObserver((m, o) => {
let potentialScript = document.querySelector("script + script");
console.log(potentialScript.textContent);
if(potentialScript) {
o.disconnect();
potentialScript
.textContent =
potentialScript
.textContent
.replace(
"})()",
`
window.wow = mySecretMethod;
})()
`
);
}
}).observe(
document.body,
{
childList:1
}
);
</script>
<script>
(function() {
let mySecretMethod = () => {
//does a bunch of evil secret stuff
console.log("HA!");
};
})();
wow()
</script>
<script>
console.log(wow())
</script>
Alternatively you can redirect the HTTP requests with a chrome extension, see https://stackoverflow.com/a/61202516/2016831 for more
If I understand what you're trying to do correctly...
If you can control how scripts A and B are loaded, the best approach is to place them on the same domain as the current page (possibly via proxy), load the files via AJAX, and insert your hooks that way. A library like jQuery as m.casey suggested would make the details of the AJAX and executing the script quite simple.
Otherwise, Javascript does not really have the ability to interact with the parsing of the document (which is what is causing scripts a and b to be loaded in your example, and what would be need to be modified to "intercept" script loading), except by using the evil of document.write to modify the HTML stream. Of course, this only works if hook.js is loaded synchronously (as it is in your example code), if it's loaded into HTML and not XHTML, if you can place a second hook afterwards to postprocess the modified HTML stream, and if you are sure the HTML stream won't escape your mechanism.
For example..
<script id="hook1">document.write("<"+"textarea id='capture'>");</script>
<script src="a.js"></script>
<script src="b.js"></script>
<script id="hook2">document.write("<"+"/textarea");</script>
<script id="hook3">doSomethingWith(document.getElementById("capture").value)</script>
Note that this is a huge hack and you probably shouldn't be doing it.
If you're using jQuery, you could have hook.js load the scripts you wish to intercept as follows:
$.getScript("a.js");
$.getScript("b.js");
This would dynamically create the script tags and you would be certain that hook.js would always proceed a.js and b.js.
Got a little problem here. Basically, I'm trying to add a script tag after the page loads.
This is what I am doing:
index.php:
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function getad()
{
$.post('assets/getad.php', "ad", function(response) {
response = response.replace('document.write','document.getElementById("ad").innerHTML = ');
eval(response);
console.log(response);
});
}
getad();
</script>
<div id="ad"></div>
</body>
</html>
getad.php:
<?php
echo file_get_contents("http://ads1.qadabra.com/t?id=a823aca3-9e3c-4ddd-a0cc-14b497cad85b&size=300x250");
?>
You can find a demo here: http://dev.cj.gy/game/
As you can see, the #ad div DOES get filled with the correct script tag, but it doesnt actually run, If I edit the page to include the script tag right at page load, it does run.
Yes, <script> tags cause execution when parsed as part of the main document; they don't execute from being written to innerHTML.
You can create an executing script element outside of that initial parse using the DOM method of calling createElement('script'), setting its src/content and adding it to the document. This is what jQuery's getScript does.
However it wouldn't do you much good because the next script, that ads1.qadabra.com is document.writeing to the page, also itself calls document.write.
You could work your way around both of these calls at the client side (ie without getad.php), by assigning your own custom function to document.write that, instead of writing to the loading page, attempts to extract the source of the script tag passed to it, and load that in a DOM-created script element.
But in general these are scripts designed to work synchronously at document load time; anything you do to try to force them to run in a way they weren't intended to is likely to be fragile and stop working when the ad network change anything.
If you want to load a third-party ad without pausing the loading of the parent document, I suggest putting it in an iframe.
So I'm trying to link up my html and javascript files in notepad++, but it isn't working properly.
I wanted to know how it is possible that it writes test, but doesn't remove the div. Can anyone explain this? Thanks in advance!
1, jQuery isn't linked. Meaning, you don't have <script type='text/javascript' src='myjQueryfile.js'></script> in your HTML, you'll want to put it before your script.
2:
Because the element with the ID of blue, doesn't exist yet. The DOM - basically the object of your HTML - has yet to be constructed when your script is run, which in this case is the top of the page, before blue comes into existence. You'll want to use an event to fix this, typically $(function(){ ... }); which will execute your code when the DOM is ready.
Also, document.write just writes code then and there, meaning exactly where the document.write calls is made, the HTML will be outputted.
You should have linked jquery. You're trying to use it without having it linked.
The script is loaded in the head. At the time the script executes the body of the document is not built, so nothing is removed. If you were to use the document.ready callback (and had properly included jQuery) it would work
$(function(){ $("#blue").remove(); });
A plain js version of this is
window.onload = function(){
var b = document.getElementById("blue");
b.parentNode.remove(b);
};
At the time the script runs, only the portion of the document up to the <script> tag has been loaded. You need to delay until the DOM has fully loaded before the script can target the DOM:
document.addEventListener("DOMContentLoaded", function(event) {
$("#blue").remove();
});
With jquery.load() I'm loading some html into my page from a file which also contains javascript functions.
later I try to remove the html and the javascript using jquery.empty but it seems once the script is parsed by the browser I can't get rid of it, so I'm looking for suggestions on how to do this.
Below is the test source:
index.html
<head>
<script src="//code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script>
$(function(){
$('#loadEmbScrpt').click(function(){
$('#embDiv').load('http://maccyd10.hostoi.com/test.html');
});
$('#remEmbScrpt').click(function(){
$('#embDiv').empty();
});
});
<body>
<div id="embDiv"></div>
<div id="output"></div>
<input type="button" id="loadEmbScrpt" value="embed script into page"/>
<input type="button" id="remEmbScrpt" value="remove embedded script from page"/>
<input type="button" id="testButton" value="run embedded script test function"/>
</body>
test.html
<script>
$('#testButton').on('click',function(){
$('#output').append("<p>test</p>");
});
</script>
And here is a link to the above in action (I could not post this to jsfiddle due to XSS protection).
http://maccyd10.hostoi.com
Have a play with this http://jsfiddle.net/6eWRQ/
As others have alluded to, the DOM and the Javascript VM are two separate systems within the browser.
The DOM is the browser's internal model of the HTML document to be rendered. It deals with HTML elements such as <script> and their position within the HTML document.
The Javascript VM deals with javascript code - it deals with running any Javascript code within <script> tags or pulled in from external js files.
it seems once the script is parsed by the browser I can't get rid of it
You can of course remove the <script> element from the DOM - but after the browser has parsed it this will have zero effect on the javascript VM - because then the javascript code inside the tag it has already been consumed and executed by the VM. Once the code has run, it cannot be un-run.
In the case of the example jsfiddle this is even clearer - removing a <script> element containing a function doesn't mean you can't call that function any more, once the code inside the <script> has already been executed by the VM. The VM has its own internal model of the function and changes to the original code in the DOM after it has been executed are simply irrelevant to it.
Removing the containing <script> element from the DOM using javascript is effectively pointless in this situation - it's just redundant. The DOM rendering engine has no use for it because it's not a visual element, and the javascript VM has no use for it because it's already-processed input.
To do what you want you should remove the #remEmbScrpt button, and instead use the following to undo the binding performed by the loaded script:
$('#testButton').off('click');
As has been mentioned in the comments, you can't get rid of javascript once it has been loaded.
With that being said, if you wish to undo the changes made by the script you posted above, the .off() function will unbind all attached to a handler (so if any other events are attached to click, they will be removed to).
e.g. the following will unbind the functions from the click events on $('#loadEmbScrpt') and $('#remEmbScrpt') :
$('#loadEmbScrpt').off('click');
$('#remEmbScrpt').off('click');
or if you want it all in one line:
$('#loadEmbScrpt,#remEmbScrpt').off('click');
Let me know if that solves your problem
Can we you get our JavaScript to run in the first place to
assign an event handler?
How can we get an initial piece of JavaScript to run without referencing a function in your XHTML page?
Just put a script tag in the body of your page and it will run as the page is rendered.
<script type="text/javascript">
// code goes here
</script>
Any code you put in a <script type="text/javascript"> tag will be executed immediately. Put it in your <head> and it will run before anything else. Put at the end of the <body> and it will run last.
Do keep in mind that the DOM may not be fully initialized in either of those cases. If you need the DOM use window.onload or jQuery's $(document).ready()
Also 'XHTML' and 'HTML' are not the same. XHTML is a very strict subset of HTML that in my opinion does nothing to improve upon regular HTML but it does allow for some fanciness. It has no effect whatsoever on JavaScript.
As you've tagged jQuery the way to do this is simply by including a ready function, e.g.
$(document).ready(function () {
// Assign your event handlers
});
Just put this code within a <script type="text/javascript"> block within your page.