I have a script element in my webpage, something like this:
<script id="myscript"></script>
Now, from a javascript file, I'm doing something like the following:
$('#myscript').src('http://foo.bar?callback=somefunc')
Now this remote script 'returns javascript' of the following form:
somefunc(somearg);
When I run all of this, things work neatly, the script gets loaded dynamically, and the 'somefunc' callback is executed.
The problem happens when I do the same thing again. Let's say I again call the same thing:
$('#myscript').src('http://foo.bar?callback=somefunc')
This, for some reason, DOESNT return the javascript call in Firefox only. (Works fine in IE - somefunc gets executed again as expected).
I can think of ugly workarounds (such as doing a $('head').append('<script...')) every time - but I'd like to know what's going on here.
Thanks in advance!
I would recommend you to use $.getScript instead of using a single script tag load scripts multiple times:
$.getScript("http://foo.bar?callback=somefunc");
That function will abstract the script element creation and its introduction to the DOM.
But it seems you are accessing a JSONP service, in that case you need only $.getJSON:
$.getJSON("http://foo.bar?callback=?", function(json){
// callback
});
I can think of ugly workarounds (such as doing a $('head').append('
Ugliness is subjective; personally, I find the technique you're trying to use (making a single script tag load multiple scripts) far uglier.
But that's not really important. Adding a new script tag works - so if you're having trouble with what you're doing, just use the normal method and live with it.
FWIW: Firefox probably doesn't respond because you're not actually changing anything... If you want to make this even uglier, append some do-nothing querystring parameter that changes each time through.
Related
I'm looking for the correct way of calling Ruby from JavaScript in the browser when building a WASM application. Naively calling a defined method doesn't work because the method isn't in scope.
The answer I've found thus far is to use the below:
rubyVM.eval("example")
Or similar with parameters:
rubyVM.eval("example 3 'some_string'")
It's the only solution I've found thus far, so I'd be interested in a better way, but it does work.
Note that because of how long the RubyVM takes to load, you will need to do something like this with your script for the RubyVM to be available:
Waiting for dynamically loaded script
I'm creating a site where newly opened pages are loaded via AJAX. Each page uses a global.js and a .js just for that page. The problem is that when I load a new page the JavaScript of the previous page will still remain no matter what.
My AJAX:
$.post({
url: "./some_url",
dataType: 'html',
data: { ajax: true },
success: function(data) {
//Here I would need a way to stop all the previous JavaScript
$("#site").empty().append(data);
}
});
Now I am looking for the best solution to this situation, because in some situations a page will have javascript running for x amount of time (by this I mean that a function will be looping doing some stuff) so I will have to add some if statement to check am I still on the correct page.
So the question is how should I solve it, is there a way to unload some javascript or maybe I should wrap all my functions into an object and null that object?
Also will the removed html elements EventListeners added via javascript be removed or will they actually stay somewhere until I manually remove them?
well AJAX is for dealing with requests in background, just for not loading all page again so... your logic seems to be invalid.
Anyway you can delete scripts in-page or links to js sources:
<script id="mustBeRemoved">....</script>
or
Then with jQuery:
$("#mustBeRemoved").remove();
Or with plain JS:
element.parentNode.removeChild(document.getElementById("mustBeRemoved"));
The fact now is when deleting it?
Just delete it when you don't need it anymore (before the AJAX request, for example, or just at the response, before loading something else).
EDIT:
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.
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 scripttag if you want to keep the DOM clean, but that's all removing it does.
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 you can analyse the js you need before coding it probably you can avoid this problems. If you project is enough developed for getting back, then the best way seems to delete the old script or link to the old script, and redeclare this functions to simply do nothing (or doing new different things).
I have an ajax script which references something in the same domain. I want to pass some HTML and then javascript associated with it. I figured that since it is not X-domain, It might let me do that. My goal is that I am taking a webservice and then returning a string which will be put into a div... when the javascript is inserted it would be fired, which allows a bunch of good stuff to happen.
I was wondering if there is anything special i need to do to pass javascript from the server across this request. My current AJAX request seems to sanitize and remove the scripts. THoughts? How would i go about this?
If you want script to be included in the AJAX response and executed by the browser, you will first need to do something similar to the article posted as a potential duplicate, excepting that you have HTML to be injected as well. Proceed injecting it as normal, but after you set the content, try something such as:
$(responseText).find("script").each(function(index, element){
var script = $(element).text();
eval(script);
}
Untested
However, I would try to find a way to avoid doing the above. JQuery provides ways to handle classes of elements added dynamically to the DOM. See: http://api.jquery.com/on/
Through a Javascript request, XMLHttpRequest responds with some additional Javascript that needs to be added to the page the requesting page.
Using eval(), if the response is something like:
alert('This is the js response');
... then this works just fine.
However, the text returned could look something like this:
<script language="javascript">var checkVar='checkVar: value 1';</script>
but most likely:
<script src="http://www.somesite.com/setCheckVarValue.js"></script>
... where additional JS needs to be loaded on the page.
I have ensured that the XMLHttpRequest is synchronous, as I want to reference checkVar right after this.
So:
<script type="text/javascript" src="http://www.mysite.com/addJSToPage.js" />
// at this point, since this is a synchronous call, page processing waits
// until the response is received that needs to include the additional JS
// to load; this, for testing sets the value of checkVar
<script type="text/javascript" >
alert(checkVar);
</script>
The alert message should read "checkVar: value 1".
For other reasons, this is not just as simple as setting var checkVar in addJSToPaged.js, so I'm not looking for that kind of recommendation.
I'm using alert(checkVar) simply as a test to ensure that a value has been set through JS in the response.
I suppose that I could strip out the beginning and ending script tags and keep the eval() way of doing it. However, I would like to know if there are any solutions that support what I'm looking for?
Thanks.
UPDATE
Following Prashanth's suggestion, in addJSToPage.js I added:
var dynamicElement = document.createElement('div');
Then in the response from the XMLHttpRequest, I did:
dynamicElement.appendChild = xmlhttp.responseText;
Still not seeing the value of checkVar.
Ignoring the fact that whatever you are doing is probably a bad idea, Prashanth has the right idea of inserting it into the DOM. you could also strip out the tags and just eval as "normal".
Not ignoring the fact that 1) eval is evil, 2) dynamically loading remote code is bad and 3) synchronous AJAX is extra bad, I have this to say:
Unless you know what you are doing, evaling anything is a bad idea, its hard to debug, can expose massive security flaws and all sorts of other nasties. You then compound this by loading remote code, which is apparently generated in a way outside of your control because you aren't able to get just the script. Synchronous Ajax is bad because there is only one thread in javascript, blocking on Ajax will literally lock up the entire page until it is loaded because even things like scrolling generate javascript events, which the currently busy engine has to check for handlers. While the request goes fast on your local machine, someone with a slow or poor quality connection could be waiting a while, up to the timeout time for the connection. The 'A' in AJAX is asynchronous, and for a good reason, use the callbacks, they are there for a reason.
If you are just doing data passing, use JSON, which is JavaScript Object Notation, a simple data format that happens to also be valid JavaScript. You can use eval on it, but I suggest a JSON parser, i think most modern browsers have them built in (could be wrong here). JSON is good because it can express complex data structures, is simple to generate and parse and is widely supported.
Recapping - the need is present to be able to dynamically load some content onto a page after/during load, and have it execute. By execute, I don't just mean change the text on some div - that's easy. But if we want to load some new JS dynamically, say an alert that comes from some outside source, and inject it, along with it's script tags, and maybe some other HTML code, then the solution is to use the following jQuery call:
jQuery(dynamicResponse).appendTo('body');
dynamicResponse comes from an asynchronous $.ajax({}) or XmlHttpRequest response. Once present, it is appended onto whatever DOM element, specified in appendTo() and executed.
Here is the example
var script = document.createElement("script");
//innerHTML can be the response from your server. But send the text with script tag.
script.innerHTML = "var foo = function(){console.log('injected into the DOM')}"
document.body.appendChild(script) // insert into the DOM
foo() // call the function
I have a relatively large (in terms of memory use and code size) JS function (running in IE/FF) that I use only occassionally (like, a couple of times per day). I think I can get rid of it when I'm done with it by nulling out its function (using the variable name of the 'function object', as it were).
I am fuzzy though on how I would get it back, supposing maybe some time later I wanted to do it again. How would I load JS on the fly from a URL like the 'script' tag does?
Does this whole line of reasoning make sense?
It's a tad hacky, but there are two ways:
Use DOM methods to insert a script tag into the page to a file that has that function in it. You might need to add a query string so that it thinks it's a new javascript file (like function.js?(random number))
Use AJAX to download the file with the function and eval(); it
The only real way to do this is to insert a script element into the document dynamically using JavaScript with a link to a script file containing your function, causing the script to be loaded. One caveat: you must make sure that the filename has the time appended as a query string, otherwise cache unfriendly browsers like Internet Explorer will not reload the script again.
Like others have said, the best bet is to go ahead and insert a new script tag into the page with some kind of query parameter to avoid caching issues. If you're using a JS Library, this technique is actually called "JSONP"; jQuery in particular has a nice method for doing this that gives you an easy way to attach a callback function and such. If you write your own native version, you'll need to watch the readystate of the new script node to know when it's actually loaded.
That said, one thing I'm curious about - and anyone else, please correct me if I'm wrong - why not use the "delete" keyword to kill your function, instead of nulling it out? Something like...
function myFunction() { return; }
Then...
delete myFunction;
Seems to be a more efficient way of cleaning things up, at least from my perspective.