remove script after load in memory [duplicate] - javascript

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);

Related

When using CasperJS, is it possible to interact with the DOM of a loaded page before any inline or external Javascript is executed?

The situation I have is that I'm opening a page using CasperJS.
The page in question has some Javascript (a combination of both inline and external) that removes several HTML elements from the document.
However, I want to be able to retrieve those elements using something like getElementsByXPath() within CasperJS before they are removed. Is this possible?
When I dump out the value of getPageContent(), the elements are not in there. However, if I set casper.page.settings.javascriptEnabled = false; before calling the page, getPageContent() now shows the raw HTML before any Javascript is executed, and the missing HTML tags are there. The problem now, though, is that disabling Javascript prevents any usage of evaluate(), so I still can't retrieve the elements. I could probably do it using a regex of some sort on the raw content, but I was hoping there could be a cleaner method of doing it.
Any suggestions welcome!
I've never heard of anyone doing this. I wouldn't say using regex is a bad idea. I usually scrape with a combination of casperjs xpath and python regex it works extremely well and I personally don't think it's any messier than trying to intercept JavaScript before the page is loaded.
That being said, casperjs allows you to inject JavaScript which you could use jquery if it's available on the page you're requesting. The below code fires before anything is loaded. You actually have to go out of your way to add code to prevent this from firing before the page loads.
<script type='text/javascript'>
alert("Stop that parsing!");
</script>

Completely remove Javascript

I have a website that has a fixed menu, header, etc. and loads the main content area via AJAX based on the menu clicks.
These "pages" rely on a lot of Javascript and CSS which are individual for each page. Since a user can potentially visit many pages, I want to unload the page-specific JS and CSS. The CSS was straight-forward, but removing the <script> tags does not remove the loaded Javascript (I can still call functions defined in it).
How can I really "remove" the JS? I don't want the memory overhead, or to have to worry about name clashes between pages.
You can load your functions into a page specific object. This will require you to make all your page specific calls though that object. When you want to unload the page, make that object point to something else (say null). Now you don't have references to the object, and it will be cleaned up by the runtime. (Assume nobody else points to it. This is trivial to enforce.)
My understanding (from this post on Perfection Kills) is that you can only completely remove javascript function declarations if they were created using eval(). If that is the case, you can remove the function by calling
delete funcName;
If the function was not created using eval(), the best you can do is redefine it. There are numerous examples of that. Here's one: javascript function redefinition

How to let JavaScript know where I am on the site?

I have a single template file which renders pages that look very similar, but behave a bit different. I have a header and a few text boxes, which are filled by the template language, and there is a canvas, whose content actually differentiates the pages. It basically comes down to calling a different JavaScript function based on the page I am on, and I can't really think of an elegant (!) way to do that.
I have a single JavaScript file that uses jQuery's document ready callback to add interactivity to the site, and also to do the drawing in the canvas. For that, I have to call a specific drawing function based on which page I am on, but I don't know it at that point.
This is certainly not impossible, I can in fact think of several different solutions, but don't really like any of these. The script file is not run through a template engine, so I can't employ any server-side logic there. I could parse the URL in the script, but this sounds like a hack to me. I could also set a variable in a script block within the template file, set a hidden field's value or something like that, but I don't think this logic belongs into the template either.
So how is this usually done?
You can give the <body> tag a "class" value, and your JavaScript code can use that (and other similar cues) to know what sorts of behaviors to add.
For example, your code could do something like:
if ($('body').hasClass('image-gallery')) {
// ... initialize image gallery code ...
}
if ($('body').hasClass('shopping-cart-summary')) {
// ... whatever ...
}
Of course it doesn't have to be just the <body> tag. Your <canvas> could also get a "class" value (and/or "data-foo" attributes) to convey information to your code.
You can embed any JavaScript you want on to a web page, built with the same server-side logic you would build the page with. So you can set global variables or (preferably) invoke functions from your .js files with parameters that contain page-specific logic. Just supply the scripts between <script> tags.
It is not clear if you want to find the page you are on, or the location in the DOM of a given page. For the former, use location.href, or location.pathname to avoid the parsing.

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.

How to not use JavaScript with in the elements events attributes but still load via AJAX

I am currently loading HTMl content via AJAX.
I have code for things on different elements onclick attributes (and other event attributes).
It does work, but I am starting to find that the code is getting rather large, and hard to read. I have also read that it is considered bad practice to have the event code 'inline' like this and that I should really do by element.onclick = foobar and have foobar defined somewhere else.
I understand how with a static page it is fairly easy to do this, just have a script tag at the bottom of the page and once the page is loaded have it executed. This can then attach any and all events as you need them.
But how can I get this sort of affect when loading content via AJAX. There is also the slight case that the content loaded can very depending on what is in the database, some times certain sections of HTML, such as tables of results, will not even be displayed there will be something else entirely.
I can post some samples of code if any body needs them, but I have no idea what sort of things would help people with this one. I will point out, that I am using Jquery already so if it has some helpful little functions that would be rather sweet!
Small code sample
This is a sample of code that is loaded via an AJAX request
<input type="submit" name="login" value="login" onclick="
if(check_login(this.form)){
Window_manager.windows[1].load_xml('login/display.php?username=' + this.form.username.value + '&password=' + this.form.password.value);
} else {
return false;
}">
I know this is small sample, but this is the sort of thing I am on about. How can I have this code attached when the content is loaded?
jQuery .live() method is probably what you are looking for. It will attach click event to newly created HTML elements, so you don't need to call your .click() with every reload of your update-panel.
You can get cleaner HTML code by making the event bindings in javascript. All you need are ways to identify the DOM objects for your HTML elements, like IDs.
If you have a link that has an ID "fooLink" you can do this in your JavaScript:
docuemnt.getElementById('foo').onclick = function () {
//do your stuff here
}
This will have the same effect as binding the event in the "onclick" attribute if the link element in your HTML code.
That way, you can produce much cleaner HTML that is easier to read and maintain.

Categories

Resources