I have a coding difficulty which have been asked in this forum before:
Calling a JavaScript function returned from an Ajax response
But I didn't find the answers quite satisfying. To be more precise of the problem I'm dealing, here is the detail:
I dynamically load a document (HTML and javascript) using jquery
var url = 'document.php';
$('#container').load(url);
Example of what the document.php looks like:
<form>
<input name="firstname"></input>
</form>
<script>
function dosomething()
{
console.log($('input[name=firstname]').val());
}
</script>
*The dosomething() function is the one I'd like to call later
And then I want to call the functions from that document.php. Due to my requirement, I don't want to call the function after the documents' loaded, but rather to call it later when I need it. Because it was dynamically loaded, the DOM doesn't recognize the functions. How to properly call this function?
Thank you
the DOM doesn't recognize the functions
This sounds like your other functions are wrapped in $(document).ready() in the remote page. If that is the case they are out of scope for you to call them from code in the main page and you need to move them out of the ready handler to make them globally accessible.
EDIT: Other possibilities
Script tags in head- move to body after html, or use $.getScript in ajax callback to retrieve
I think that you're trying to implement the technique called on-demand javascript (or lazy-loading). In other words, your page should initially load just a small script - but use a bunch of objects and functions, which are available in some other files, but will be loaded when they're required.
If that's the case, I have to warn you: you'll probably need to update your existing code. Instead of just calling some function right as it is, in all gun-blazing glory, you should check for its existence first - and if it's not available, wait for its loading:
if (typeof lazyObjects.someLazyFunction !== 'function') {
lazyLoad('lazyFunction.js');
}
lazyObjects.someLazyFunction();
The key point here is that lazyLoad should be synchronous. In other words, you'll have to wait until the script containing your function is actually loaded. Otherwise someLazyFunction just won't be defined when it's called, even with this sort of checks.
lazyFunction.js, in turn, will contain some code that will alter lazyObjects, adding to them the required method as a property:
// in lazyFunction.js
lazyObjects.someLazyFunction = function() { ... }
While it's technically possible to use global (=window) object for these cases, I usually don't do this - and won't recommend doing it either.
See, it's not that simple. ) I'd recommend reading this article to find out more about this technique - and actually using some established components to implement it in your code (some of them are mentioned in the linked article).
Related
In my app, I'm using a script tag to load an externally-hosted JS script. This script defines a function which I want to call on the frontend when it's loaded, and to pass certain variables. So you could imagine this file looks something like this:
window.someFunc = (args) => {
// do something
}
And then in my frontend HTML:
<script src="/someFile.js" onload="someFunc('hello')"></script>
This works, but if I change window.someFunc to const someFunc, it no longer works, because the onload doesn't have access to someFunc. It seems to me non-ideal that I have to attach the function to the window object. Is there a way to avoid this and still access this function in the onload of the script tag?
I know this question seems pretty basic, but I've done a number of searches and can't find an answer about how to do this neatly.
What I need is pretty simple, although I don't know if possible..
I'm attaching all my event handlers to the object themselves instead of to $(document).
But, I need to attach them on the .ready() method, to make sure the object is created before the handler is attached. Since there are a lot of handlers to attach, to keep my code cleaner I want to create a function called attachHandlers() that will be called on document.ready().
But.. this function should execute codes that are in multiple files.
My question is.. is there a way of declaring the same function multiple times, and then calling it just once to execute them all?
But.. this function should execute codes that are in multiple files.
My question is.. is there a way of declaring the same function
multiple times, and then calling it just once to execute them all?
If interpret Question correctly, you want to request javascript from multiple files at .ready() . You can create an array containing url of file to request, use $.when(), $.map(), $.getScript() to call the javascript within the files
jQuery.getScript( url [, success ] ) Returns: jqXHR
Description:
Load a JavaScript file from the server using a GET HTTP request, then
execute it.
The script is executed in the global context, so it can refer to other
variables and use jQuery functions. Included scripts can have some
impact on the current page.
$(document).ready(function() {
var files = ["1.js", "2.js", "3.js"];
$.when.apply($, $.map(files, function(file) {
// request file
return $.getScript(file)
}))
.then(function() {
// complete
// do stuff
}, function err(jqxhr, textStatus, errorThrown) {
// handle error
});
});
Create a global JS file that has this function (and future functions that you want to be run on all pages). Call this script at the top of each file in the head element. Calling it in the head should do what you need (at least that is what i use in my projects and works for me).
Can u package your multiple files in modules and every one of them has a method attachHandlers? Then try use requirejs to load all of them. In document.ready, call the attachHandlers method from all these modules? It will be neater
I am new to JSONP and had implemented cross domain functionality for my application and everything is working fine. Now i want to change my javascript code to apply object orientation.
My api is
http://localhost:8080/myApplication/getComments?callback=displayComments
CrossDomain.prototype.displayComments = function(data) {
// code to display the comments
}
Now I am getting an error in firebug given below
ReferenceError: displayComments is not defined
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
{
//code to display the comments
}
this time another error in firebug
SyntaxError: function statement requires a name
I have a doubt whether to use JSONP in object oriented javascript or not.
Please help.
Thanks in advance.
There's no point in defining the function on the prototype of a function unless you are going to create instances of that function, so start by doing that.
var myCrossDomain = new CrossDomain();
Then you have to call the method on the object, not as a global (it isn't a global, so you can't do that anyway)
var uri = "http://localhost:8080/myApplication/getComments?callback=" +
encodeURIComponent("myCrossDomain.displayComments");
In response to edits and comments:
Yes i am creating an instance of this in another js file
Then reference it as shown above.
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
It's JSON-P. It runs by adding a new script element. Everything gets called in the global context. That is going to call this.displayComments which will be the same as window.displayComments.
If you want to call your method directly, then you need to specify the global variable holding the instance explicitly.
If you don't want to call it directly then you can use the more traditional approach of generating a new, anonymous function which has access to said object through a closure, assigning that function to a global variable (with a unique name) and using that name as your callback argument.
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
You haven't shown us the code that creates the URI so we can't tell why that might be the case.
I have an javascript object that includes some image strings as its property. Upon instantiating this object, an AJAX call is made immediately to populate this property.
My view functions, at the same time, tries to read newly instantiated instances and tries to display this object. As expected, the AJAX call may not have finished by then yet, so it will not be able to read the right image url.
One solution to this problem is to pass in some call back function with the AJAX call that modifies the source of image upon completion, but this is introducing a lot of dependency on the model and the view and I'm trying to keep my MVC as separate as possible, so my view function right now just takes that object as an parameter, reads all the properties, and shows it.
Making the AJAX synchronous isn't an option because I have quite a lot of these objects being initialized and only one will be displayed at a time, so making all AJAX calls synchronous will be too expensive of a tradeoff.
What's a good way to solve this problem? The view function is something in the form of:
function displayObj(object) {
var prop1 = object.getProp1();
// this could be the image file that depends on AJAX result
var prop2 = object.getProp2();
}
Ideally, I would like to delegate this task to the getter, so that the view function doesn't have to worry about the interval state of the the object. The getter could handle this by checking whether the image is there yet, if not, wait, then only return if the actual image string is there. However, a blocking wait would for sure block the AJAX process so it's a deadlock, and non-blocking wait will let the getter return and the view function will get null data.
Please shed some light on this situation or suggest alternative ways that I can organize my code. Thank you very much!
I'd be a little bit less strict with the MVC roles and let the model object return the DOM <img> object.
// model object starts loading upon instantiation
var loader = new Loader();
// however the img tag is available immediately.
// the loader will update the src when ajax
// calls complete.
document.body.appendChild(loader.getImg());
Since, from your comments, you are using jQuery I recommend you call the done() method of the request returned from the ajax() method. For example,
var request = $.ajax("example.php");
request.done(notifyWhenSuccess);
request.fail(notifyWhenFailed);
This request returned by jQuery is a superset of the Promise pattern from CommonJS. Also, just because it is in jQuery don't cosider the ajax call part of the view but rather view it as part of the model. Use the done() method to update the model then notify the view with a data changed event.
I want to call a Javascript function from Flash, which I can do with ExternalInterface, but the Javascript function takes a callback. Is there a way to give it a Flash callback?
I've thought of something like this:
ExternalInterface.addCallback("foo", function(){...});
ExternalInterface.call("theFunction", "foo");
But that wouldn't work since theFunction would attempt to do foo(), while it should really do swfObject.foo(). The problem is the page and its Javascript are not under my control (though I can request changes if really needed).
This is closely related to the first question in the related questions section.
Along the same lines as the answer to that question, you can do:
ExternalInterface.addCallback("foo", function() { /* ... */ }); // The callback
ExternalInterface.call("theFunction(function() { swfObject.foo(); })");
You're misunderstanding the documentation, I think. callback in this instance is just a reference to a function inside Flash, not a callback to something you call.
Basically, you use .call() to call a JS function from AS; and you use .addCallback() to tell the Flash Player which AS function should be called based on the name.
On your example, theFunction would get one parameter as being 'foo', which is the name that references your anonymous AS function. Not sure why you would want to pass the function like that, but if you need, you could just call it from JavaScript with
function theFunction(callback) {
// .. do something...
swfObject[callback]();
}
Now, if you don't have control over the JS/HTML side, I'm not sure if you can do that. Not sure why you'd need, anyway - JS calls are synchronous, as if they were running on the same thread, meaning the Flash Player will execute the JS code and only then return to the Flash Player... you don't have to wait for execution or anything.
Also, if you really need to control the page without touching the JS/HTML side, remember you can inject entire pieces of JS code via .call - it doesn't need to be a simple function call. You can create your entire functions from inside the SWF. For example,
var js:XML = <script><![CDATA[
// Javascript code...
]]></script>;
ExternalInterface.call(js);
Or, if you need the return data, you don't need a callback either - just do a simple call as in
// JS
function isNumberZero(__num) {
return __num == 0;
}
// AS
trace ("Is number zero = " + ExternalInterface.call("isNumberZero", 10));
Not sure if this helps at all. If not, it'd be good to have more information on what exactly you're trying to do.