editing the <head> section with javascript - javascript

I would like to clear the entire head section once the page loads... actually, my goal would be to delete all JavaScript code held in the head section.
Is there some way to do something like this:
document.head.innerHTML = "";
Explanation:
I am using a Python script that uses Qt and webkit to take screenshots of websits.
It works on most sties, but there is one that it fails on. That site has a bunch of JavaScript code that it runs on timeouts. The WebKit webpage object allows me to execute JavaScript on the page. If there is some way to have the JavaScript remove all of the code form the head section I'd like to be able to try that for testing purposes to see if it resolves my screenshot script issue.

You can remove elements from the head, but it wont matter. The scripts have already run and removing the elements wont unload them or anything.

document.getElementsByTagName("head")[0].innerHTML = "";
// IE
var htmlEl = document.getElementsByTagName("html")[0];
htmlEl.removeChild(document.getElementsByTagName("head")[0])
var el = document.createElement("head");
htmlEl.appendChild(el);
To stop JavaScript scripts running by setTimeout, you should use clearTimeout, but for this case you should have a handler... But you're lucky, if they are defined as global variables.

Try using:
document.getElementsByTagName('head').innerHTML = "";
to clear the head. document.head does not exist so this may not work.
But you may want to try to disable the JavaScript using JavaScript like suggested by noah.
See http://www.manticmoo.com/articles/jeff/programming/javascript/removing-javascript-with-javascript.php for directions. It sounds crazy but evidently it works.

As noah said, simply removing the code from the head tag won't accomplish anything. You have to actually undo what the code is doing. For example, if it's using setTimeout() to set up the timeout code you're complaining about, you need to use clearTimeout() to disable it.

$('#id').empty();
Worked very well.

Related

Undo jQuery or revert DOM?

I have some jQuery that runs on a page. As a short-term fix I want to remove the code within the tags (containing the JS), that are on the page so that this jQuery does NOT run.
Is there any way that I can do this, or stop the code from running? I want to revert back to the typical DOM state, not the manipulated one...
Edit:
I have a script tag on the page that runs some javascript.
Due to certain limitations, I can't simply remove this - I have to include a javascript file to remove this script tag / OR prevent this javascript from running.
I want to revert back to how the page should look without having been manipulated by the script tag that is already on the page.
If you can only include a javascript file, you could try re-declaring the jquery object so it can't run:
jQuery = null;
$ = null;
That would kill jQuery providing it's loaded after. This however would probably cause of lot of javascript errors. On that trail of thought, you could just plug in some broken JS and it would stop jQuery from executing if it's before the jQuery stuff.
I can't think on a scenario where it's needed.
And indeed it's impossible to revert the DOM after manipulation. reset button doesn't revert the DOM
if its in a method you can just use return false; before your code runs, you can also just comment out your code, or wrap your code in a method that never runs:
$("p").hide();
becomes:
function() {
$("p").hide();
}
Or have I misunderstood your question?
Just move your code out of the jQuery(document).ready function, that should make the HTML stay the way it was.
After reading your additions in edit, I think the only to see the page before loading that script would be to add a break-point using Firebug script console at that particular script.
Edit: Add further answer after reading the OPs edit.
the only way I can think of you achieving this without manipulating the source or dom would be to test for a cookie prior to code execution,if it does not exist then set it and continue executing the rest of your code something like this. When you want to revert changes made in the dom back to the 'original' just refresh the window and the existence of the cookie will prevent execution a second time
(function() {
if($.cookie('foo') == null) {
$.cookie('foo', 'bar');
$('#alert').click(function() {
alert('run');
});
}
})();
the only flaw I can see in this is if a user rejects the cookie in which case if it really matters I would alert the user and again break out of execution

How to pass jQuery to eval'd code?

First, check out my fiddle fiddle
jsFiddle is nice, but sometimes it runs a bit slow, so I made this simple pure JS fiddle (can be ran locally)
Working great so far, but I want to be able to use jQuery in my fiddle. Type alert(typeof $); in the bottom left box and press "Run" to see what I mean (says undefined).
So how do I pass jQuery off to the iframe and give it the correct context? I suspect I could set doc.contentWindow.$=$ or something like that, but I still need to give the correct context so it knows where to find the elements. How would I do that?
iframe.contentWindow.$ = $.proxy($,iframe.contentWindow);
That didn't work either. Gives me access to jQuery, but the context is still wrong.
iframe.contentWindow.$ = function(s){return $(s,doc);};
That sort of works... but it's a bit of a hack.
Why not do as jsfiddle itself does? It simply includes a script tag for jQuery (or whatever framework you asked for) in the head of the iframe.
If you look in head of the... uh "outer" iframe (the one jsfiddle created), you'll see they just threw this in there:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.js"></script>
Same thing applies to the "on ready" and "on load" options, jsfiddle just wraps the appropriate call around your javascript before injecting it into the iframe.
Modifying your code a little, you can create a script element:
var doc = iframe.contentWindow.document;
var jqueryTag = doc.createElement('script');
jqueryTag.type = 'text/javascript';
jqueryTag.src = 'http://code.jquery.com/jquery-1.6.4.js';
and then append that element to the head.
I tweaked your fiddle fiddle a little: http://jsfiddle.net/gilly3/XcSYz/3/
First, you can't write a doctype to the body's innerHTML and expect it to do anything for you. Same with a charset meta tag. I moved all of that to a document.write call.
You were evaluating script tags oninput of the editors. First this throws errors like crazy if you are editing a script tag in the html frame. Second, if you put an alert("hello") in a script tag in the HTML pane, then with every keypress, you get an alert. Third, you were evaluating the scripts in the context of the parent window. I changed html script tags to be evaluated when run is clicked and with the correct context.
Since you don't want to re-write the document every time (you can't, eg doctype), I modified it slightly to do some dom manipulation instead. It removes and replaces the style tag and writes only the HTML pane contents to the body's innerHTML.
This is a fun little project you are trying. jsFiddle is buggy and needs some updates. I don't know how viable your pure client-side fiddle is - jsFiddle is quite robust (despite its bugs), but it is a nice exercise to give your approach a try.
Edit: One more change included in this version: I modified your textareas to use width: 50%; height: 50%; instead of setting right and bottom. Those weren't working properly in IE or FF.

How to dynamically add a Javascript function (and invoke)

Based on a click event on the page, via ajax I fetch a block of html and script, I am able to take the script element and append it to the head element, however WebKit based browsers are not treating it as script (ie. I cannot invoke a function declared in the appended script).
Using the Chrome Developer Tools I can see that my script node is indeed there, but it shows up differently then a script block that is not added dynamically, a non-dynamic script has a text child element and I cannot figure out a way to duplicate this for the dynamic script.
Any ideas or better ways to be doing this? The driving force is there is potentially a lot of html and script that would never be needed unless a user clicks on a particular tab, in which case the relevant content (and script) would be loaded. Thanks!
You could try using jQuery... it provides a method called .getScript that will load the JavaScript dynamically in the proper way. And it works fine in all well known browsers.
How about calling eval() on the content you receive from the server? Of course, you have to cut off the <script> and </script> parts.
If you're using a library like jQuery just use the built-in methods for doing this.
Otherwise you'd need to append it to the document rather than the head like this:
document.write("<scr" + "ipt type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></scr" + "ipt>");
In all honesty, I have no idea why the script tag is cut like that, but a lot of examples do that so there's probably a good reason.
You'll also need to account for the fact that loading the script might take quite a while, so after you've appended this to the body you should set up a timer that checks if the script is loaded. This can be achieved with a simple typeof check on any global variable the script exports.
Or you could just do an eval() on the actual javascript body, but there might be some caveats.
Generally speaking though, I'd leave this kind of thing up to the browser cache and just load the javascript on the page that your tabs are on. Just try not to use any onload events, but rather call whatever initializers you need when the tab is displayed.

Initiate onclick faster than with document.onload

I have html-pages with links where i want to attach a function to their onclick event. One way to do it is of course:
Save
But I know this is not the best practice. So instead I wait for window.onload, loop through the links and attach the save-function to the links with rel="save". The problem with this is that it waits until the whole page has finished loading which can be several seconds after the link is displayed and clickable.
So is there another way to do this? Avoiding onclick in the html but that makes it work immediately when the link is rendered.
Internet Explorer has a handy attribute for <script> tags called defer. It's for delaying the parsing of a script until the document has finished loading. For other browsers that support it, you can use DOMContentLoaded, as someone else suggested and for browsers that don't support either you can fall back to onload.
<script type="text/javascript" defer>
//- Run this code when the DOM parsing has completed
</script>
I did a quick Google search for "DOMContentLoaded defer" and found the following page that might help:
http://tanny.ica.com/ica/tko/tkoblog.nsf/dx/domcontentloaded-event-for-browsers
In your case, you can just leave that as it is. Stick to the simplest possible thing, even if it is not the general best practice.
You could try DOMContentLoaded event instead of load. IE also gives you the defer attribute for script tags, which defers execution until the DOM is loaded. If those don't work for you, then you are stuck with the solutions you mention, as far as I know.
I don't know if this is appropriate for your solution, but you could insert script immediately below the are with the links you need altered. This script would not be wrapped in a function, allowing the browser to execute it immediately when seen. The effect is that you can run script before the full page is loaded, altering only the items that exist above the script being run. (If you reference something below the script, it will fail.)
BTW, this is almost certainly not a best practice, and some would probably label it a worst practice.
How about this?
Save
Note: This solution requires to users to have Javascript enabled. Not exactly best practice, but may be suitable for your scenario.
The ideal here would be to use the ideas of Unobtrusive Javascript.
In this way, if the Javascript isn't loaded the link would still do something. It's a link right, so it leads the user to another piece of content? - this should work without Javascript. And if the functionality attached to the links can ONLY work with Javascript you should create and insert them into the DOM with Javascript (they aren't clickable if they aren't there...).
(Otherwise how about delegating the click event to a wrapper element? Does that work before the element is complete?)
edit: Oh, and "save" sounds very much like it ought to be a button in a form rather than a link. The Unobtrusive JS stuff still applies though.

JavaScript - controlling the insertion point for document.write

I would like to create a page that runs a 3rd party script that includes document.write after the DOM was already fully loaded.
My page is not XHTML. My problem is that the document.write is overwriting my own page. (which is what it does once the DOM was loaded).
I tried overriding the document.write function (in a way similiar to http://ejohn.org/blog/xhtml-documentwrite-and-adsense/) but that doesn't cover cases where the document.write contains partial tags.
An example that would break the above code is:
document.write("<"+"div");
document.write(">"+"Done here<"+"/");
document.write("div>");
Is there some way to modify the document.write insertion point through JavaScript? Does anyone have a better idea how to do this?
If you're dealing with 3rd party scripts, simply replacing document.write to capture the output and stick it in the right place isn't good enough, since they could change the script and then your site would break.
writeCapture.js does what you need (full disclosure: I'm the author). It basically rewrites the script tags so that each one captures it's own document.write output and puts it in the correct place. The usage (using jQuery) would be something like:
$(document.body).writeCapture().append('<script type="text/javascript" src="http://3rdparty.com/foo.js"></script>');
Here I'm assuming that you want to append to the end of the body. All jQuery selectors and manipulation methods will work with the plugin, so you can inject it anywhere and however you want. It can also be used without jQuery, if that is a problem.
It is possible to override the document.write method. So you can buffer the strings sent to document.write and output the buffer wherever you like. However changing a script from synchronous to asynchronous can cause errors if not handled correctly. Here's an example:
Simplified document.write replacement
(function() {
// WARNING: This is just a simplified example
// to illustrate a problem.
// Do NOT use this code!
var buffer = [];
document.write = function(str) {
// Every time document.write is called push
// the data into buffer. document.write can
// be called from anywhere, so we also need
// a mechanism for multiple positions if
// that's needed.
buffer.push(str);
};
function flushBuffer() {
// Join everything in the buffer to one string and put
// inside the element we want the output.
var output = buffer.join('');
document.getElementById("ad-position-1").innerHTML = output;
}
// Inject the thid-party script dynamically and
// call flushBuffer when the script is loaded
// (and executed).
var script = document.createElement("script");
script.onload = flushBuffer;
script.src = "http://someadserver.com/example.js";
})();
Content of http://someadserver.com/example.js
var flashAdObject = "<object>...</object>";
document.write("<div id='example'></div>");
// Since we buffer the data the getElementById will fail
var example = document.getElementById("example");
example.innerHTML = flashAdObject; // ReferenceError: example is not defined
I've documented the different problems I've encountered when writing and using my document.write replacement: https://github.com/gregersrygg/crapLoader/wiki/What-to-think-about-when-replacing-document.write
But the danger of using a document.write replacement are all the unknown problems that may arise. Some are not even possible to get around.
document.write("<scr"+"ipt src='http://someadserver.com/adLib.js'></scr"+"ipt>");
adLib.doSomething(); // ReferenceError: adLib is not defined
Luckily I haven't come across the above problem in the wild, but that doesn't guarantee it won't happen ;)
Still want to try it out? Try out crapLoader (mine) or writeCapture:
You should also check out friendly iframes. Basically it creates a same-domain iframe and loads everything there instead of in your document. Unfortunately I haven't found any good libraries for handling this yet.
Original Answer before the edit:
Basically the problem of document.write is that it does not work in XHTML documents. The most broad solution then (as harsh as it may seem) is to not use XHTML/xml for your page. Due to IE+XHTML and the mimetype problem, Google Adsense breaking (may be a good thing :), and the general shift towards HTML5 I don't think it's as bad as it seems.
However if you'd really like to use XHTML for your page, then John's script that you linked to is the best you've got at this point. Just sniff for IE on the server. If the request is from IE, don't do anything (and don't serve the application/xhtml+xml mimetype!). Otherwise drop it into the <head> of your page and you're off to the races.
Re-reading your question, is there a specific problem you have with John's script? It is known to fail in Safari 2.0 but that's about it.
You may be interested in the Javascript library I developed which allows to load 3rd party scripts using document.write after window.onload. Internally, the library overrides document.write, appending DOM elements dynamically, running any included scripts which may use document.write as well.
Unlike John Resig's solution (which was part of the inspiration for my own code), the module I developed supports partial writes such as the example you give with the div:
document.write("<"+"div");
document.write(">"+"Done here<"+"/");
document.write("div>");
My library will wait for the end of the script before parsing and rendering the markup. In the above example, it would run once with the full string "<div>Done here</div>" instead of 3 times with partial markup.
I have set up a demo, in which I load 3 Google Ads, an Amazon widget as well as Google Analytics dynamically.
FWIW, I found postscribe to be the best option out there these days - it handles wrapping a pesky ad rendering module like a charm allowing our page to load without being blocked.
In order to alter the content of the page after the DOM has rendered you need to either use a javascript library to append HTML or text at certain points (jQuery, mootools, prototype, ...) or just use the innerHTML property of each DOM element to alter/append text to it. This works crossbrowser and doesn't require any libraries.
There are better ways to do this.
2 ways
1) Append
<html><head>
<script>
window.onload = function () {
var el = document.createTextNode('hello world');
document.body.appendChild(el);
}
</script></head><body></body></html>
2) InnerHTML
<html><head><script>
window.onload = function () {
document.body.innerHTML = 'hello world';
}
</script></head><body></body></html>

Categories

Resources