How to set function as value to property that expects anonymous function - javascript

I'm using jquery API - jquery DataTables and I have this code snippet :
oSettings.aoDrawCallback.push({
"fn": function(){
},
"sName": "user"
});
Inside the body of the function I want to execute an Ajax request. when I write it drectly here like so:
"fn": function(){
$.ajax({
url: "url",
type: "POST",
async: false,
data: data,
success: function (data) {
console.log(data);
}
}),
There is more that is just an example to show the way everything's work fine. Then I create my own function :
function initCredits(id, inputVal, chkSelected) {
console.log(id);
$.ajax({
url: "URL",
type: "POST",
async: false,
data: data
success: function (data) {
}
})
}
and try to assing it do fn like so:
oSettings.aoDrawCallback.push({
"fn": initCredits(id, inputVal, chkSelected),
"sName": "user"
});
which gives me an error Uncaught TypeError: Cannot read property 'apply' of undefined. Now the text comes from the jquery DataTables API but there may be only two reasons I can think of that may break my code, since it's working befor taking it to outer function. First - I'm tryng to assing the function in a wrong way and second - as you may see I need three variables for my ajax request (id, inputVal, chkSelected) which are collected from the function where I'm doing this :
oSettings.aoDrawCallback.push({
"fn": initCredits(id, inputVal, chkSelected),
but the console log shows that the values are correct so I think this is less likely to be the problem, but still I consider it.

This:
"fn": initCredits(id, inputVal, chkSelected),
… calls the function and assigns the return value.
To assign the function, just do:
"fn": initCredits,

Related

JQuery prototyping functions

I am trying to create a prototype of the ajax object.
I have created these functions:
$.extend({
ajax_prototype : function(parammeters){
instance = this;
instance.cache = false;
instance.crossDomain = false;
instance.dataType = 'json';
instance.timeout = 30000;
instance.error = default_error_function;
$.each(parammeters,function(key,value){
instance[key] = value;
});
},
set_ajax_action : function(template,action,func,def){
template[action] = func;
}
});
ajax_prototype
Is a constructor for the object.
Sets some default settings and some defined based on every need.
set_ajax_action
Sets the function to be executed on each event.
When I create an object like this:
temp1 = new $.ajax_prototype({
'type' : 'post',
'url' : 'controller.php',
});
I get this object:
Object { cache: false, crossDomain: false, dataType: "json", timeout: 30000, error: default_error_function(), type: "post", url: "controller.php", success: function () }
But after I use this:
$.set_ajax_action(temp1,'error',function(){console.log();});
The object becomes like this:
Object { cache: false, crossDomain: false, dataType: "json", timeout: 30000, error: function (), type: "post", url: "controller.php", success: function () }
Basicly their difference is the way error function is set.
Both objects work prety good.
But I would like to make the prototype to create the object with the second form.
Can someone explain me why the difference on the two objects and how to resolve my problem?
Edit 1
I can also create the second object even if I remove the error property from my prototype and call $.set_ajax_action(...) .
My problem is why there is difference to the functions presentation to console.
I know my question is trivial and that either way the result would be the same, but I wan to know how it works.
By the way, even if I set the error property like this:
instance.error = function(){ ... };
The result will be:
Object { cache: false, ifModified: false, processData: true, crossDomain: false, dataType: "json", timeout: 30000, error: .ajax_prototype/instance.error(), url: "test" }
Console is able to trace if a function can be identified somehow. For example, if it has a name or it is assigned to variable, console will show its/variable's name. If it's created inside a function, console will show it. Example:
(function testt(){
$.set_ajax_action(temp1,'error',function(){console.log();});
})()
console.log(temp1)
this code will produce error: testt/<() (firefox).
You can hide name of function, not giving your default handler a name. For example, like this:
(function(default_error_function){
$.extend({
ajax_prototype : function(parammeters){
instance = this;
...
instance.error=default_error_function
...
},
set_ajax_action : ...
});
})(function() {/* default error handler */})
Here, scope of default_error_function symbol is not global, therefore console does not show it. At the same time, handler was created outside any other function, so console only has function () to show.

Execute multiple functions with parameters to be fired in order on ajax sucess

I'm attempting to write a couple of functions using jQuery to help me test some api endpoints that I'm writing in php. I'm a novice when it comes to Javascript and jQuery and I'm having difficulty working out what I need to read up on in order to get things working that way I need it.
Here are the requirements I'm attempting to meet:
Call should be non blocking
Functions only to be fired on success and in order
I need to pass parameters along with the functions rather than just function names
Each function needs to be able to access the data variable return by success: function(data) from within the api() function
I've read the jQuery docs and believe that deferred and promises are possibly the avenue I should be pursuing but I am not able to get an example working.
Simplified versions of my two functions:
(For clarity)
// Returns data from an api request providing something hasn't gone horribly wrong
function api( api, method, endpoint, query ) {
$.ajax({
type: method,
url: '/api/' + api + '/' + endpoint,
data: query,
dataType: 'json',
success: function(data) {
// I currently have a single hardcoded function
populate( data.result, '#resource', null );
},
error: function( data ) {
// Debug
dump(data.result);
}
});
// Do some other stuff here
}
// Example call
$('body').on('click', '#bigFatButton', function() {
// I would like to specify a function (or chain of functions)
// to be fired on success along with the api() function
api('resources', 'get', 'document', {
debug: '1',
id: '7'
})
});
This is what I'd like to achieve (something nice, short and reusable):
fn1() and fn2() are fired in order and can both access the data returned by api()
api('resources', 'get', 'document', {
debug: '1',
id: '7'
}).fn1(data, 'custom', 'params').fn2(data, {other: 'params'}).alert('wooty!');
What would be the best way of achieving something similar to this? A nudge in the right direction would be very much appreciated!
Thank you.
Try adding return statement before $.ajax() , returning data from api , utilizing .then()
function api( api, method, endpoint, query ) {
// return `$.ajax()` jQuery promise to `.then()`
return $.ajax({
type: method,
url: '/api/' + api + '/' + endpoint,
data: query,
dataType: 'json',
success: function(data) {
// I currently have a single hardcoded function
populate( data.result, '#resource', null );
// return `data`
return data
},
error: function( data ) {
// Debug
dump(data.result);
}
});
// Do some other stuff here
}
// Example call
$('body').on('click', '#bigFatButton', function() {
// I would like to specify a function (or chain of functions)
// to be fired on success along with the api() function
api('resources', 'get', 'document', {
debug: '1',
id: '7'
}).then(function(data) {
$.when(fn1(data, 'custom', 'params')
, fn2(data, {other: 'params'})
.then(function() {alert('wooty!')})
})
});
Due to the asynchronous nature of AJAX you can't chain functions directly from the API function. The data would simply not be available when the chained functions are ran. However you can do it inside the success function. You will need to construct a wrapper function.
function wrapper()
{
return {
fn1 : function(data){
//execute code for fn1 here
return wrapper();
},
fn2 : function(data){
//execute code for fn2 here
return wrapper();
},
alert : window.alert.bind(window);
}
}
}
By running wrapper.fn1(data, arguments).fn2(data, arguments).alert("whoot!") inside the success function it will work the way you intended.
Everytime you call upon the wrapper function, or a function inside it it will return the full object allowing for function chaining.
A more efficient design would be to construct the functions outside the wrapper object and only reference them inside the wrapper function.
1 - I would use the methods as arguments in an anonymous function
api('resources', 'get', 'document', {
debug : true, // better to say true or false :)
id : 7, // if your id is a number use number
callback : function(data){
fn1(data);
fn2(data);
}
});
2 - Using an array, could be cool if you have a lot to run.
// in api method..
for(var i; i < cbks.lengths; i++){
cbks[i](); // execute one by one the callbacks declared.
}
api('resources', 'get', 'document', {
debug : true, // better to say true or false :)
id : 7, // if your id is a number use number
[fn1, fn2, fn3] // here are the callbacks
});

Unable to get value from json object

I am trying to get a value from a json object after making an ajax call. Not sure what I am doing wrong it seems straight forward but not able to get the data
The data that comes back looks like this
{"data":"[{\"Id\":3,\"Name\":\"D\\u0027Costa\"}]"}
The code, removed some of the code
.ajax({
type: 'POST',
url: "http://localhost:1448/RegisterDetails/",
dataType: 'json',
data: { "HomeID": self.Id, "Name": $("#txtFamilyName").val()},
success: function (result) {
console.log(result.data); //<== the data show here like above
alert(result.data.Id); //<==nothing show
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
I tried in the Chrome console like this
obj2 = {}
Object {}
obj2 = {"data":"[{\"Id\":3,\"Name\":\"D\\u0027Costa\"}]"}
Object {data: "[{"Id":3,"Name":"D\u0027Costa"}]"}
obj2.data
"[{"Id":3,"Name":"D\u0027Costa"}]"
obj2.data.Id
undefined
obj2.Id
undefined
Update
The line that solved the issue as suggested here is
var retValue = JSON.parse(result.data)[0]
Now I can used
retValue.Name
to get the value
Actually, looking at this, my best guess is that you're missing JSON.parse()
.ajax({
type: 'POST',
url: "http://localhost:1448/RegisterDetails/",
dataType: 'json',
data: { "HomeID": self.Id, "Name": $("#txtFamilyName").val()},
success: function (result) {
var javascriptObject = JSON.parse(result);
console.log(javascriptObject ); //<== the data show here like above
alert(javascriptObject.Id); //<==nothing show
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
I also find that doing ajax requests like this is better:
var result = $.ajax({
url: "someUrl",
data: { some: "data" },
method: "POST/GET"
});
result.done(function (data, result) {
if (result == "success") { // ajax success
var data = JSON.parse(data);
//do something here
}
});
For clarity it just looks better, also copying and pasting into different functions as well is better.
The id property is in the first element of the data-array. So, alert(result.data[0].Id) should give the desired result. Just for the record: there is no such thing as a 'JSON-object'. You can parse a JSON (JavaScript Object Notation) string to a Javascript Object, which [parsing] supposedly is handled by the .ajax method here.
The data field is just a string, you should parse it to a JSON object with JSON.parse(result.data), since data is now an array you will need to need to use an index [0] to have access to the object. Know you will be able to get the Id property.
JSON.parse(result.data)[0].Id

How can I pass an object in addition to json from my ajax function?

I have the following code:
function submitHandler(dialog) {
dialog.$submits.disableBt();
dialog.$message.addMessage("loading", "<li>Contacting Server, please wait ...</li>");
$.ajax({
url: href,
dataType: 'json',
type: 'POST',
data: dialog.$form.serializeArray()
})
.done(onSubmitDone())
.fail(onSubmitFail());
}
This function has a parameter of dialog which is an object looking like this:
{
$modal: $modal,
$form: $modal.find('.form'),
$message: $modal.find('.message'),
$submits: $modal.find('.submit-button'),
href: $form.attr('data-href')
};
I need to send the dialog object to the onSubmitDone and onSubmitFail functions. Previously I was not using an object
to hold $modal, $form etc and the variables were all available to all functions that were enclosed within an outer function
Two questions:
Is it sensible to pass things around as parts of an object or should I just declare these variables at the top of an outer function.
If I do pass around the object how can I pass it to the following:
function onSubmitDone(json) {
json = json || {};
if (json.Success) {
switch (action) {
I understand that my json object is passed but how can I pass the dialog object also?
One way of passing your dialog argument to the ajax callbacks is to enclose it in the callbacks definition, as showed bellow:
function submitHandler(dialog) {
dialog.$submits.disableBt();
dialog.$message.addMessage("loading", "<li>Contacting Server, please wait ...</li>");
$.ajax({
url: href,
dataType: 'json',
type: 'POST',
data: dialog.$form.serializeArray(),
success: function(data, textStatus, jqXHR) {
onSubmitDone(data, textStatus, jqXHR, dialog);
},
error: function(jqXHR, textStatus, errorThrown) {
onSubmitFail(jqXHR, textStatus, errorThrown, dialog);
}
});
}
I made explicit all callback arguments (data, textStatus, jqXHR, errorThrown), but you don't need to use all of them if you don't want to.
If you pass your object as the context option of $.ajax, it will be available as this inside onSubmitDone and onSubmitFail:
var jsonObj; // do you really need this global?
function submitHandler(dialog) {
jsonObj=dialog.$form.serializeArray();
dialog.$submits.disableBt();
dialog.$message.addMessage("loading", "<li>Contacting Server, please wait ...</li>");
$.ajax({
url: href,
dataType: 'json',
type: 'POST',
data: jsonObj ,
context: dialog
})
// Don't call the handlers from here, no ()!
.done(onSubmitDone)
.fail(onSubmitFail);
}
// Receives the data from the server
function onSubmitDone(response) {
// your object is available as 'this':
console.log(this.$modal);
}
// Different params here, but 'this' is the same
function onSubmitFail(jqXHR, textStatus) { /* ... */ }
Underscore js is a unique and really awesome library for object handling and manipulation
Since you want to pass your object is wise to declare it outside of the functions
Then you can access your object's parts and work with them in your functions' body.
Your code will look like this:
var jsonObj;
function submitHandler(dialog) {
jsonObj=dialog.$form.serializeArray();
dialog.$submits.disableBt();
dialog.$message.addMessage("loading", "<li>Contacting Server, please wait ...</li>");
$.ajax({
url: href,
dataType: 'json',
type: 'POST',
data:jsonObj
})
.done(onSubmitDone(jsonObj))
.fail(onSubmitFail(jsonObj));
}
Regarding your question if it is sensible to pass the object around, while you can, you might find it gets a little burdensome to do so, needing to lug the variable around whenever you need to use it. I would recommended encapsulating your dialog object in the parent scope of your submitHandler() function so it is available to submitHandler, onSubmitDone, etc.
Regarding your second question if you were to pass it around and how you'd get the dialog object to your onSubmitDone function as well, you can always pass the response and your dialog object to your onSubmitDone function like so:
.done(onSubmitDone(response, dialog))

Looking for parse assistance

This is the view from my browser:
{
"data": {
"request": [{
"query": "Lat 41.85 and Lon -87.65",
"type": "LatLon"
}],
"time_zone": [{
"localtime": "2012-02-14 16:05",
"utcOffset": "-6.0"
}]
}
}
Now, I am using this code to parse it:
function getTimeZone(latlong) {
jQuery(document).ready(function ($) {
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=[removed]&q=" + latlong + "&format=json",
dataType: "jsonp",
success: function (parsed_json) {
console.log(parsed_json.time_zone.utcOffset);
return parsed_json.time_zone.utcOffset;
},
error: function (parsed_json) {
//console.log("Error: " + parsed_json);
}
});
});
}
Every time I run the code, I am getting this error:
Uncaught TypeError: Cannot read property 'utcOffset' of undefined
Any assistance would be greatly appreciated.
View of the data being displayed to the console (only copied the part I'm interested in):
Result:
Object
data: Object
request: Array[1]
time_zone: Array[1]
0: Object
localtime: "2012-02-14 16:46"
utcOffset: "-6.0"
Actually, there are two issues:
1) to access the content, you need:
parsed_json.data.time_zone[0].utcOffset;
2) This is a bit more complex - you are using an asynchronous ajax callback - success() is not being called before your program finishes sending the ajax request and returns, and it does not return its results to the parent method.
The basically can't do it the way you want to, unless you use a synchronous fetch (a bad idea, since it'll lock up your browser until the response arrives).
Instead, take a callback parameter, which will be a function, as a parameter to your function, and call that with the result once it arrives:
i.e.
function getTimeZone(latlong, callback) {
jQuery(document).ready(function ($) {
$.ajax({
url: "http://www.worldweatheronline.com/feed/tz.ashx?key=[removed]&q=" + latlong + "&format=json",
dataType: "jsonp",
success: function (parsed_json) {
console.log(parsed_json.time_zone.utcOffset);
callback(latlong, parsed_json.data.time_zone[0].utcOffset);
},
error: function (parsed_json) {
//console.log("Error: " + parsed_json);
}
});
});
}
Then to use it:
getTimeZone(myLatLong, function(latLong, utcOffset) {
// ... do something with utcOffset here ...
});
Should be
return parsed_json.data.time_zone[0].utcOffset;
You have to look carefully at the returned JSON structure. It helps to break it up into separate lines and indent to reflect the nesting.
should it be parsed_json.data.time_zone[0].utcOffset?

Categories

Resources