I was wondering how I can get a function from an AJAX request, like this:
Let's say I have a file called myfunction.js, that looks like this:
function(bar){
alert(bar);
}
Can I retrieve it via Ajax as a function, like this?
var foo = $.ajax({url:'myfunction.js',async:false}).responseText;
And run it like this?
foo(bar);
The reason I ask is because I know responseText is a string,
so I'm not really sure if JavaScript will understand that it is a function.
Is there a way to convert a string into a function?
In your JS file, give the function a name.
function foo(bar){
alert(bar);
}
Then use $.getScript to load it.
$.getScript('myfunction.js', function(){
foo('test');
});
Absolutely:
foo = eval('(' + foo + ')');
foo(bar);
You could use new Function but in my testing it doesn't work on some versions of IE.
I ended up using new Function instead of eval, eval executes the code as soon as it's parsed, which is not what I was after.
This is what I ended up doing, and it works very nicely in firefox, chrome, and IE 7+ (no errors at all)
function createMyFunction(code){return new Function('params',code)};
var thecode = $.ajax({
url: 'myCode.js',
async: false,
dataType: 'html'
}).responseText
myFunction = createMyFunction(thecode);
I know the createMyFunction is pretty lazy in terms of not being able to define different arguments, but using a single params map works for my templating scenario quite well.
Note the dataType:'html' in the ajax request, if you don't specify a plain text mime type, jQuery will actually recognize that you are getting JS code and try to parse it, which generally ends up throwing a parse error or sometimes "Uncaught TypeError: params is not defined".
With this, I am able to have template files that specify template-specific events, and keep them organized in the same way as the markup and css files for that template.
Thanks for the help everyone, the reason I chose the answer that I did is because the link at the end pointed me in the right direction.
Cheers,
D
One thing to beware.
Chrome and IE don't allow you to eval an anonymous function directly (FF is fine). That is
// Throws Syntax Error in Chrome, Object expected in IE 8
var fun = eval('function(){return 5}'); fun();
A hackaround is to put it in an array, doesn't seem very reliable for the future:
var fun = eval('[function (){return 5}][0]'); fun();
The only safe way would be to make sure your functions are named, since the following works fine in all browsers:
eval('function a(){return 5}]'); a(0);
See Are eval() and new Function() the same thing? for further discussion
Related
I have the following function which I use to render partial views in my app. Yet it is not filling the element I pass it with any content.
function RenderPartialView(view, contentcontainer, maskcontainer, params) {
$.get(view, params, function (data) {
$("#" + contentcontainer).html(data);
$(maskcontainer).unmask();
})
}
I call this function from various methods with in my app and as of now have had no trouble with it. At the moment though, I'm prepending a div to the page and then calling this function from a method like so in order to fill the div with the html data from RenderPartialView.
loadExpandedDashboard: function () {
RenderPartialView('../Metrics/ExpandedDashboard', 'expanded-view', '#expanded-view');
}
everything works fine in all other browsers, in IE8 I do not get any console errors and when running basic error checking callbacks everything is clean. If I log the 'data' returned from the $.get() it shows the full length html that I am requesting from my own server. Because of this I'm completely lost on what could be the cause, Any ideas would be greatly appreciated. Thanks!
My guess would be that there is something in the returned HTML - missing or out of order tags, etc. - that IE is having trouble with. IE is known for being picky about the markup it accepts when in the html() method, whereas other browsers are more lenient.
Strangely, setting the innerHTML property directly sometimes works when jQuery's html() function does not.
I have a very odd problem that I have to assume is because of Yabble.js. I have never used Yabble.js before, and the only reason I am now is because it is a dependency of a library I'm using (Gamejs), but I would love to understand why this happens, and whether it is actually Yabble.js's fault, or possibly Gamejs's.
Here's a heavily compressed (and modified for genericness) version of my main.js:
var gamejs = require('gamejs');
...
function Character(/*lots of arguments*/) {
Character.superConstructor.apply(this, arguments);
this.somethingtomakeitaprototypeforthisexample = oneofthearguments;
}
gamejs.utils.objects.extend(Character, gamejs.sprite.Sprite);
Character.prototype.draw = function(display){
display.blit(this.animator.image, this.pos);
}
... /*Skipping most of the file, irrelevant to the problem*/
function main() {
maincharacter = new Character(/* appropriate number and types of arguments */);
... /*skipping the rest*/
}
gamejs.ready(main);
I have done enough debugging to know that it gets into the main function no problem and that the break occurs at the call to Character. Here is the error message (from Chrome's console):
Uncaught TypeError: undefined is not a function
main
_readyResources
I have determined that Character is the undefined function. However, if I define my ready function thusly:
gamejs.ready(function(){
console.log('Character:');
console.log(Character);
main();
});
the full contents of Character, as properly defined, prints out, but I still get the error in main. Thus, I know that Character is defined by the namespace before main is called.
Fun fact though: I do have a workaround. If I change the function prototype for main to:
function main(CharacterClass) {...};
then change the ready function to:
gamejs.ready(function(){ main(Character); });
and change the relevant line in main to:
var character = new CharacterClass(...);
it works fine. But this feels really hackish.
So my question is not how to make it work, since I have that already, but rather why it is a problem and how to make it work like it's supposed to.
Any thoughts?
I'm using jQuery's $.when() to handle multiple $.get() requests. This is how I have it set up.
var request1 = $.get('myURL');
var request2 = $.get('mySecondURL');
$.when(request1, request2).done(go);
function go(request1, request2){
console.log(request1);
console.log(request2);
}
Everything works great. Chrome's console shows
[#document, "success", Object]
I know that #document is what I need to read, but what is the syntax to get it? Every example I've seen uses anonymous functions, which I'm not use to and bug me, coming from OOP AS3.
I've tried console.log(request1[0]); which works, but there has to be a more proper way. Something like request1.data or $(request1).$('#document');
Like I said, I'm a heavy Flex developer coming into JS and jQuery so the syntax I'm still trying to pickup.
According to the documentation for $.when, request1[2] has the jqXHR object, which in turn has responseText member. If you use console.log in Chrome at least, you can see the contents of the jqXHR to find what member you specifically want to access, but it's probably responseText.
Create a jQuery object and use it like you would use one created from a selector: $(request1)
For example, $(request1).appendTo('#out') would append the newly loaded content to an element with id="out".
I've been working with JavaScript and i need to call a function from another .js file.
The code works most of the time, but sometimes it gives me the error "Object has no method odometer". I've even put the code inside a call to getScript() to make sure it's loaded before it tries to call the odometer() function, but I'm still getting random errors.
Heres the code:
var updateDisplay = function(){
console.log("refreshing Odometers");
$.getScript("/odometer.js", function(){
$.getJSON(
'/getData',
{
product: '',
unit: unitSelection(),
period: salesPeriod(),
reportBegin: $("#datepickerfrom").val(),
reportEnd: $("#datepickerto").val()
},
function(data){
$(".odometer").odometer({
odometerData:data
});
});
});
};
I am getting an error on this line:
$(".odometer").odometer({
odometerData:data
});
It says "object has no method odometer".
I am using the Play framework for development and I've already imported jQuery and my other JavaScript files in the HTML page.
Here's my JS import order:
jquery
odometer.js (even i use getScript, i've put it there just to make sure)
main.js (which the given code resides in..)
What am I doing wrong?
Thanks for helping....
I think
$(".odometer").odometer({...})
is called before odometer extends to jQuery, flow may be like this
$(".odometer").odometer({...}); // first called
$.fn.odometer = function(){...}; // later it was extended to jQuery
seems like its a problem with ajax caching settings.
i've found the answer from this question:
jquery ajax bug
after adding
$.ajaxSetup({ cache: true });
the getScript works fine. thanks for spnding your time guys :)
I'm using jQuery 1.3.2 and it's breaking under Safari 4 for mysterious reasons.
All of my javascript references are made right before the tag, yet with the following code:
var status = $('#status');
status.change( function(){ /* ... */ } );
The following error is displayed in the Web Inspector:
TypeError: Result of expression 'status.change' [undefined] is not a function.
However the error is not encountered if I eliminate the variable assignment attach the change method directly like so:
$('#status').change( function(){ /* ... */ } );
Why? I need to use variables for this and several other findById references because they're used many times in the script and crawling the DOM for each element every time is regarded as bad practice. It shouldn't be failing to find the element, as the javascript is loaded after everything except and .
Try changing the variable to something other than "status."
It's confusing your variable with window.status (the status bar text). When I typed var status = $('#status') into the debugging console, the statusbar changed to [Object object]. Must be a bug in Safari.
If you put the code inside a function, so that status becomes a function-local variable, it should work.
It's standard practice in jQuery to wrap things in a
$.onready(function() {
});
This makes sure the DOM is loaded before you try to manipulate it.