I am looking for a better method of doing something that is common in JavaScript. How do I do this:
// global namespace
var PlexLib = PlexLib || {};
PlexLib = {
FileName : "",
ShowName : "",
AddFileSelector_result : function (data,status,xhr) {
console.log ("Callback here." + data);
console.log ("Callback here." + status);
console.log ("Callback here." + xhr);
},
AddFileSelector : function () {
var afs = this.AddFileSelector_result();
$.get(script_name ,"AddFileSelector=AddFileSelector",afs,"html");
},
RemoveFileSelector : function () {
console.log ("Do Remove.");
},
}
Ok, at $.get(script_name ,"AddFileSelector=AddFileSelector",afs,"html")
the problem is with afs.
The specification of .get request is:
$.get(URL,data,function(data,status,xhr),dataType)
What I am getting up above is when the callback occurs, I am either getting 'undefined' in the data, (data,status,xhr) or, the entire script passed in. I have no idea how that's happening either.
So, what I am asking is, when I see a definition like:
$.get(URL,data,function(data,status,xhr),dataType)
How do I do the function(data,status,xhr) part, I want it to be a reference to a normal:
function () {
}
defined someplace else.
Don't call the function here:
var afs = this.AddFileSelector_result();
Pass it as a pointer:
var afs = this.AddFileSelector_result;
so that when the AJAX request completes it will be invoked with the proper arguments.
Related
This code is not working as expected. I am trying to use the Google Geolocation API to figure out my current location. However, when I try to log the result for the google.maps.LatLng object, I got (0,0) as the latitude and longitude coordinates.
$(document).ready(function(){
var func = {
lat:0,
long:0,
success:function(pos) {
var crd = pos.coords;
this.lat = crd.latitude;
this.long = crd.longitude;
},
error:function(err) {
console.log('ERROR(' + err.code + '): ' + err.message);
},
init:function(){
navigator.geolocation.getCurrentPosition(this.success, this.error);
}
};
func.init();
$('button').on('click',function(){
var loc = new google.maps.LatLng(func.lat, func.long);
alert(loc);
});
});
However, the code underneath works. All I did was changing "this" keyword to the object's name. It shouldn't make a difference.
$(document).ready(function(){
var func = {
lat:0,
long:0,
success:function(pos) {
var crd = pos.coords;
func.lat = crd.latitude;
func.long = crd.longitude;
},
error:function(err) {
console.log('ERROR(' + err.code + '): ' + err.message);
},
init:function(){
navigator.geolocation.getCurrentPosition(func.success, func.error);
}
};
func.init();
$('button').on('click',function(){
var loc = new google.maps.LatLng(func.lat, func.long);
alert(loc);
});
});
I am not sure why the code snippet on the top produces incorrect output? I am not too familiar with Objected Oriented JavaScript. I would appreciate it if anyone could help me understand what is going on.
In your first example, when you call:
getCurrentPosition(this.success, this.error);
You are merely passing the success and error functions into getCurrentPosition. Even though you reference them here via this, that is not carried through to the point where the functions are actually called. It only passes the function references themselves, not the this value that you were using here.
Another way to understand the problem: the value of this inside a function is determined at the time the function is called. When you write foo.bar() you are calling the bar() function with foo as the this value inside the function. But when you write foo.bar without the (), you are only getting a reference to bar itself. foo is out of the picture after that. If you pass foo.bar into another function which expects a callback, when it finally calls bar() there is no longer any association with foo.
That's why your second example works. It does not depend on this but uses func which is valid throughout the outer function.
Morning all,
I'm using the following code to somewhat imitate setInterval with AJAX:
// Poll for ALERTs
(function pollForAlerts() {
var params = { "send": 1, "poll": 1 };
// Set up the correct patch for sending AJAX data
ALERTS = {};
ALERTS.Auth = { site: data_site, uuid: data_uuid };
ALERTS.API = function(app,data) {
var url = "//myurl.com/alerts/"+ app +"/?";
var data = $.extend({}, ALERTS.Auth, data);
return url + jQuery.param(data || "") + '×tamp='+$.now();
}
// Run the AJAX request
$.getJSON( ALERTS.API( 'touchscreen', params ) , function (response) {
if( typeof response === "object" ) {
for( var i = 0; i < response.length; i++ )
renderAlert(response[i]);
} else { setTimeout( pollForAlerts, 3000 ); }
});
}());
The function runs repeatedly until it finds a response.
I'd like to then set a jQuery ".on" to restart this loop if a certain element is clicked on:
// Respond to ALERT
$('#alerts').on('click', 'td.initials span', function(event) {
$(this).closest('tr').removeClass("active abs cri");
pollForAlerts();
});
However, when I do that, I get the following error in Firebug:
ReferenceError: pollForAlerts is not defined
http://myurl.com/alerts/static/js/touchscreen.js
Line 14
I can't work out why pollForAlerts() can't be accessed. Is it because of the self-executing function, or is it just because it's being used within jQuery's on function?
I'm not JavaScript expert, especially when it comes to self-executing functions and closures, so please be gentle with me!
Duncan
You wrote self invoking function, These functions are executing only once in lifetime. If you want to call a function multiple times then you can write it as normal function.
I'm using a jQuery Ajax request in a prototype function. I want the user to be able to pass his own complete and beforeSend functions into this function. These user-functions then should get extracted from the options and put into my own beforeSend and complete functions so I can do some system stuff in them before the user functions are triggered.
I made this fiddle to clarify. See how the link "With Options" is working as expected and the link "Without Options" is not. Click it several times to see what I mean:
http://jsfiddle.net/xwmoaepc/1/
function jBox() {
this.options = {
ajax: {
url: 'http://stephanwagner.me/ajax/0/SYSTEM RESPONSE',
data: ''
}
}
}
jBox.prototype.ajax = function (options) {
$('#log').append('<div class="first">function prototype.ajax started<div>');
// Abort running ajax call
this.ajaxRequest && this.ajaxRequest.abort();
// Merge options
var ajaxOptions = jQuery.extend(this.options.ajax, (options || {}));
// Extract events
var beforeSend = ajaxOptions.beforeSend || function () {};
var complete = ajaxOptions.complete || function () {};
// Set new beforeSend event
ajaxOptions.beforeSend = function () {
$('#log').append('<div style="color: #d66">SYSTEM-beforeSend<div>');
(beforeSend.bind(this))();
}.bind(this);
// Set new complete event
ajaxOptions.complete = function (response) {
$('#log').append('<div style="color: #6d6">SYSTEM-complete: ' + response.responseText + '<div>');
(complete.bind(this))(response);
}.bind(this);
// Send new ajax request
this.ajaxRequest = jQuery.ajax(ajaxOptions);
};
// Create instance
var jBox = new jBox();
// This function is working!
function triggerAjaxOpt() {
var userOptions = {
url: 'http://stephanwagner.me/ajax/0/USER RESPONSE: ' + $('input').val(),
beforeSend: function () {
$('#log').append('<div style="color: #66d">USER-beforeSend<div>');
},
complete: function () {
$('#log').append('<div style="color: #66d">USER-complete<div>');
}
};
jBox.ajax(userOptions);
}
// This function will have more and more beforeSend and complete outputs
function triggerAjax() {
jBox.ajax();
}
Also note, that when you change the number 2 to 3 after you clicked the not working link, it will not change the response.
EDIT: It's working now, this is what i ended up with:
http://jsfiddle.net/xwmoaepc/3/
Try this and it'll work:
var ajaxOptions = jQuery.extend((options || {}), this.options.ajax);
If you have this.options.ajax as the first argument of extend it'll mutate this.options.ajax see code below:
//see what the following line does when second argument is an object
// not having beforesend (if it has then it'll be overwritten)
//var ajaxOptions = jQuery.extend(this.options.ajax, (options || {}));
var org = {id:"org"}
var copy = jQuery.extend(org,{});
console.log(copy===org);//true as copy is a reference to org
copy.id="copy";//mutating members in copy affect org
console.log(org.id);//=copy
Now the statement:
ajaxOptions.beforeSend = function () { ...
is the same as:
this.options.ajax.beforeSend = function() { ...
So the first time it'll be undefined and the local variable beforeSend will be an empty function.
The second time the local variable beforeSend will be this.options.ajax.beforesend and this.options.ajax.beforesend is re assigned with a function that calls the local variable beforesend that will call the closure beforesent (empty function)
The third time you call ajax ...
I'm making my first steps with javascript objects combined with php objects. So far everything is working fine, but I struggle to access the javascript object created in the ajax success response outside of this function.
Here is my JS code:
function settings(mannstage, stundenlohn, tags) {
this.mannstage = mannstage;
this.stundenlohn = stundenlohn;
this.tags = tags;
}
var currentSettings;
SendAjaxJsonRequest("getSettings");
function SendAjaxJsonRequest(method, jsonObject) {
jsonObject = (typeof jsonObject === "undefined") ? "none" : jsonObject;
$.ajax({
type: "POST",
url: "app/class/controller/ajax.php",
data: {
method: method,
jsonObject: jsonObject
},
success: onSuccess
})
};
function onSuccess(content) {
var response = $.parseJSON(content);
currentSettings = new settings(response.mannstage, response.stundenlohn, response.tags);
console.log(currentSettings); //Returns the object
}
console.log(currentSettings); //This is undefined
The last console.log is undefined. How can I make currentSettingsaccessible outside the onSuccess function?
Thank you!
Ajax is asynchronous, so the last console.log will be executed before the success function is called.
currentSettings is accessible outside the onSuccess function, but your last console.log call runs immediately after onSuccess is defined, which is before it's been called, so the value of currentSettings is still undefined at that point.
Maybe editing your code like this will demonstrate it:
function onSuccess(content) {
var response = $.parseJSON(content);
currentSettings = new settings(response.mannstage, response.stundenlohn, response.tags);
console.log(currentSettings); //Returns the object
afterSuccess(); // Also returns the object
}
function afterSuccess() {
console.log(currentSettings);
}
I'm discovering the concept of "objects" in JavaScript. I'm making an RSS Parser, and I have an error (commented).
function MyParser (feed_url) { // Construct
"use strict";
this.feedUrl = feed_url;
this.pubArray = [];
if (typeof (this.init_ok) == 'undefined') {
MyParser.prototype.parse = function () {
"use strict";
var thisObj = this;
$.get(this.feedUrl, function (data, textStatus, jqXHR) {
if (textStatus == 'success') {
var xml = jqXHR.responseXML,
//lastBuildDate = new Date($(xml).find('lastBuildDate').text());
items = $(xml).find('item');
items.each(function () {
var pubSingle = thisObj.makeObj($(this).find('pubDate').text(),
$(this).find('link').text(),
$(this).find('title').text(),
$(this).find('description').text(),
$(this).find('encoded').text(),
$(this).find('commentRss').text(),
$(this).find('comments').last().text());
thisObj.pubArray.push(pubSingle);
});
console.log(thisObj.pubArray); // OK
}
}, 'xml');
console.log(this.pubArray); // Empty
return (this.pubArray);
};
MyParser.prototype.makeObj = function (pubDate, pubLink, pubTitle, pubDesc, pubContent, pubComCount, pubComLink) {
"use strict";
var pubSingle = {};
pubSingle.pubDate = new Date(pubDate);
pubSingle.pubLink = pubLink;
pubSingle.pubTitle = pubTitle;
pubSingle.pubDesc = pubDesc;
pubSingle.pubContent = pubContent;
pubSingle.pubComCount = pubComCount;
pubSingle.pubComLink = pubComLink;
return (pubSingle);
};
}
this.init_ok = true;
}
If you look at the console.log(), you'll see that the line // OK is outputting my array correctly.
But later, when returning from $.get, my array is empty.
Does anybody have an idea why, and how to correct that please?
This is not a problem with variable-scope. The problem here is that you're working with asynchronous flow and you're not thinking correctly the flow.
Let me explain:
When you do your .get, you fire a parallel asynchronous process that will request information from the browser, but your main program's flow keeps going, so when you get to your "return" statement, your array has not been filled yet with the response from your get method.
You should use your array from inside the get callback and not outside of it, since you can't guarantee that the array will have the information you need.
Does it make any sense?
Let me know!
Further explanation
According to your comments, you're still doing something like this:
var results = MyParser(feed_url);
//code that uses results.pubArray
And you cannot do that. Even though you're setting your "pubArray" inside your .get callback, you're trying to use pubArray right after you called MyParser and that's before the .get callback is called.
What you have to do, is call your next step on your program's logic from within the .get callback... that's the only way you can be sure that the pubArray is filled with proper data.
I hope that makes it clearer.
This is because your line
console.log(this.pubArray); // Empty
is being called directly after you issue your Ajax request; it hasn't had time to fetch the data yet. The line
console.log(thisObj.pubArray); // OK
is being called inside the Ajax callback, by which time the data has been fetched.
Thank you all, and particulary #Deleteman .
Here is what I did:
$.get(this.feedUrl, 'xml').success(function () {
thisObj.handleAjax(arguments[0], arguments[1], arguments[2]);
$(document).trigger('MyParserDone');
}).error(function () {
$(document).trigger('MyParserFailed');
});
Then, when i enter "HandleAjax", i'm back in my object context, so "this" refers to my object and the right properties. The only "problem" is that I have to set a listener (MyParserDone) to make sure the parsing is finished.