I'm using the following code:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
alert("This gets executed afterwards");
});
alert("This gets executed first");
event.infoWindowHtml = "<b>Address: </b>" + address;
}
}
Problem is the $.getJSON function gets executed after the 'address' variable is used in the infoWindow. Modified the code like this:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
});
}
}
The 'event' object doesn't seem to be accessible this way (nothing is displayed in the Google Maps infoWindow). I figured I should be able to pass 'event' to the function inside the JSON but I have no idea how to accomplish this.
Try this:
function eventListenerTest(event, callback) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
callback();
});
}
}
Then:
eventListenerTest(event, function(){
// you will use updated event object here
});
You should use $.proxy method to make sure that the callback function that gets executed keeps the context of the function creating the Ajax call.
Updated Javascript:
function eventListenerTest(event) {
if (document.getElementById('gem_cvo_select_list')) {
var address;
$.getJSON(url, $.proxy(function (data) {
address = data.rows[0];
event.infoWindowHtml = "<b>Address: </b>" + address;
},this));
}
}
More information: http://api.jquery.com/jQuery.proxy/
Related
I'm trying to automate the navigation of some web pages with phantomJS.
What i'm trying to create is a pattern for testing and navigation, so far i got this.
For a moment ignore all the potential null pointers due to empty arrays and such :)
testSuite.js
var webPage = require('webpage');
// Test suite definition
function testSuite(name){
this.name=name;
this.startDate=new Date();
this.tests=[];
this.add=function(test){
this.tests.push(test);
};
this.start=function(){
console.log("Test Suite ["+this.name+"] - Start");
this.next();
},
this.next=function(){
console.log("neeext");
console.log(this.tests.length);
var test=this.tests[0];
this.tests.splice(0,1);
console.log("Test ["+ test.name+"]");
test.execute();
};
}
//Test definition
function test(name,testFunction){
this.name=name;
this.execute=testFunction;
}
module.exports.testSuite=testSuite;
module.exports.test=test;
FirstPageModule.js
var currentPage;
function onPageLoadFinished(status) {
var url = currentPage.url;
var filename='snapshot.png';
console.log("---------------------------------------------------------------");
console.log("Status: " + status);
console.log("Loaded: " + url);
console.log("Render filename:" + filename);
console.log("---------------------------------------------------------------");
if(status == 'success'){
currentPage.render(filename);
}
if(status=='fail'){
console.log("Status: " + status);
}
}
function open(){
currentPage.open("http://localhost:8080");
}
function login(){
var username="topSecretUsername";
var password="topSecretPassord";
currentPage.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js");
currentPage.evaluate(function(user,pass) {
$("#user").val(user);
$("#pass").val(pass);
},username,password);
currentPage.render("page.png");
currentPage.evaluate(function(){
$('#loginButton').click();
});
}
function FirstPage(){
var page = webPage.create();
currentPage=page;
this.testSuite = new testSuite("FirstPageModule");
this.testSuite.add(new test("Open First Page",open));
this.testSuite.add(new test("Login",login));
var onLoadFinished=onPageLoadFinished;
var callNextTest=this.testSuite.next;
currentPage.onLoadFinished=function(status){
onLoadFinished.apply(this,arguments);
callNextTest();
};
page.onConsoleMessage = function(msg) {
console.log(msg);
}
}
module.exports=new FirstPage();
PageTests.js
var firstPage=require('./FirstPageModule.js');
firstPage.testSuite.start();
What i want to do is to have a sequential execution of isolated functions, after each function gets executed, i take a screenshot and call the next function.
But, for some reason, the next method on the testSuite isn't getting called, or the method on the second test isn't getting executed.
What am i doing wrong?
Just make available the logName variable in the "global" scope :
var logName;
function onPageLoadComplete(status){
console.log(status);
// Call the logName function
if(typeof(logName) == "function"){
logName();
}
}
function test(){
var page = webPage.create();
this.name="TestName";
// Update logName value as a function.
logName = function(){
console.log(this.name);
}
page.onLoadFinished = onPageLoadComplete;
}
Primary, it doesn't seems to be related to phantomjs but only plain javascript, i hope that's what you need, otherwise please be more specific with your question.
You can create your own page.get implementation with a callback when a page is fully loaded.
ex: create a file module pageSupport.js
// attach listeners
Object.prototype.listeners = {};
// store and fire listeners
Object.prototype.addEventListener = function(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
this[event] = function(e) {
if (listeners[event]) {
listeners[event].forEach(function(listener) {
listener.call(null, e);
});
}
}
}
// create a new reference to webpage.open method
Object.prototype._open = Object.open;
// receive an url and
// return a function success that will be called when page is loaded.
Object.prototype.get = function(url) {
return {
success : function(callback) {
this.open(url);
this.addEventListener('onLoadFinished', function(status) {
if (status == 'success') {
return callback(status);
}
});
}.bind(this)
}
}
// export as phantomjs module.
exports.Object = Object;
So you can call this module in your script and uses it as follows:
var page = require('webpage').create();
require('./pageSupport');
page.get('http://stackoverflow.com').success(function(status) {
// Now this callback will be called only when the page is fully loaded \o/
console.log(status); // logs success
});
I'm working on practicing with the openweathermap api. I have a coordinate object with keys lat & lon which are equal to a string. When I pass that coord obj into another function and try to concat those strings with the api call string they become undefined. I thought I made the scope of these variables global but it doesn't seem to be the case. Can someone tell me what is incorrect about this code
var apikey = '9575f3355ae129dc91424b5712a7695e';
var coords = {};
var accessOWM='';
function myLocation(){ navigator.geolocation.getCurrentPosition(function(position) {
coords.lat = (Math.round(position.coords.latitude*100)/100).toString();
coords.lon = (Math.round(position.coords.longitude*100)/100).toString();
});
}
function changeAccess(coordObj, key){
console.log(coordObj);
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat='+coordObj['lat']+'&lon='+coordObj['lon']+'&APPID='+key;
}
myLocation();
console.log(coords);
changeAccess(coords, apikey);
console.log(accessOWM);
That's because getCurrentPosition method is asynchronous. This mean that getCurrentPosition's callback is not invoked at the moment of calling changeAccess function. So you have to place changeAccess call into getCurrentPosition's callback:
function myLocation() {
navigator.geolocation.getCurrentPosition(function(position) {
coords.lat = (Math.round(position.coords.latitude*100)/100).toString();
coords.lon = (Math.round(position.coords.longitude*100)/100).toString();
});
changeAccess(coords, apikey);
}
You have an issue with async code. navigator.geolocation.getCurrentPosition(successCallback) function is an asyncronious function, the successCallback will not be executed immedeately, but with some delay. That is why when you call console.log(coords) and changeAccess(coords, apiKey), the coords are not defined yet. You need to call these functions (and the last one) from inside the .getCurrentPosition() callback.
Since coords is declared in the parent scope of changeAccess, you don't need to pass coordObj into changeAccess. Have you tried:
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat='+ coords.lat + '&lon=' + coords.lon + '&APPID='+key;
Either
var apikey = '9575f3355ae129dc91424b5712a7695e';
var accessOWM;
function round(v){ return Math.round(v*100)/100 }
function myLocation(){
navigator.geolocation.getCurrentPosition(function(position){
changeAccess(position.coords);
});
}
function changeAccess(coords){
console.log(coordObj);
accessOWM ='http://api.openweathermap.org/data/2.5/forecast?lat=' + round(coords.latitude) + '&lon=' + round(coords.longitude) + '&APPID=' + apikey;
console.log(accessOWM);
}
myLocation();
Or
var apikey = '9575f3355ae129dc91424b5712a7695e';
var accessOWM = myLocation().then(changeAccess);
accessOWM.then(function(v){
console.log(v);
})
function round(v){ return Math.round(v*100)/100 }
function myLocation(){
return new Promise(function(resolve){
navigator.geolocation.getCurrentPosition(function(position){
resolve(position.coords);
});
});
}
function changeAccess(coords){
return 'http://api.openweathermap.org/data/2.5/forecast?lat=' + round(coords.latitude) + '&lon=' + round(coords.longitude) + '&APPID=' + apikey;
}
This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 years ago.
I'm trying to retrieve data from JQuery function and pass it into global variables to use with Google Maps. These variables have to stay global, otherwise Google Maps don't work with them. I manage to get all data that I need from AJAX url and it logs perfectly but only inside Jquery function. If I log it outside of it, it's undefined. Is there anyway to pass those values to global variables?
function displayMarkers() {
var latlng = new google.maps.LatLng(latitd, longtd);
var name = titleName;
createMarker(latlng, name);
}
var latitd;
var longtd;
var titleName;
$(document).ready(function() {
$('#earthquakes').click(function() {
getQuakes();
});
function getQuakes() {
$.ajax({
url: 'http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + yesterDate + '&endtime=' + displayDate,
success: function(data) {
console.log(data);
$.each(data.features, function(key, val) {
var coord = val.geometry.coordinates;
locationD = {
latd: coord[0],
lngd: coord[1]
};
latitd = locationD.latd;
longtd = locationD.lngd;
titleName = val.properties.title;
console.log(latitd, longtd);
console.log(titleName);
});
}
});
}
});
Your code should be like this
var latitd;
var longtd;
var titleName;
$(document).ready(function () {
$('#earthquakes').click(function () {
getQuakes();
});
});
function getQuakes() {
$.ajax({
url: 'http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + yesterDate + '&endtime=' + displayDate,
success: function (data) {
console.log(data);
$.each(data.features, function (key, val) {
var coord = val.geometry.coordinates;
locationD = {
latd: coord[0],
lngd: coord[1]
};
latitd = locationD.latd;
longtd = locationD.lngd;
titleName = val.properties.title;
console.log(latitd, longtd);
console.log(titleName);
//Call this function to display here after success ajax
displayMarkers();
});
}
});
}
function displayMarkers() {
var latlng = new google.maps.LatLng(latitd, longtd);
var name = titleName;
createMarker(latlng, name);
}
Add an async:false to your ajax request.
To be able to push markers to the map i need to have the returned data outside of the querying function, but I cant get the data out or return it from the query, how can i make it a global variable, or how can I return the object so I can access it in the rest of the script (not just in the success: function), any help would be appreciated
var query = new Parse.Query("business_and_reviews");
var results = new Parse.Object("business_and_reviews");
query.get("pLaARFh2gD", {
success: function(results) {
console.log(results["attributes"]["lat"]);
lat = results["attributes"]["lat"];
lng = results["attributes"]["lng"];
myLatLng2 = (lat + "," + lng);
console.log(myLatLng2);
myLatLng = new google.maps.LatLng(myLatLng2);
},
error: function(object, error) {
}
});
//lat = results.get(["attributes"]["lat"]);
console.log(lat);
}
You can create a global object (if you really want) and reference it directly in the success object.
However, I'd personally use callbacks to handle the data for both success and fail.
You'd end up with something along the lines of:
//success callback
function createMap(data){
var latlong = data["attributes"]["lat"] + ',' + data["attributes"]["lng"]
var map = new google.maps.LatLng(latlong);
}
//fail callback
function failure(reason){
console.log(reason)
}
//initialising function used to call the API
function initMap(){
getLatLong(createMap, failure)
}
//handles api with callbacks supplied
function getLatLong(successCallback, failCallback){
var query = new Parse.Query("business_and_reviews");
var results = new Parse.Object("business_and_reviews");
query.get("pLaARFh2gD", {
success: function(results) {
if(typeof successCallback ==='function') {
successCallback(results)
}
},
error: function(object, error) {
if(typeof successCallback ==='function') {
failCallback(error)
}
}
});
}
//call the function
initMap();
I am using jQuery to call a controller, the controller is returning a value. the jQuery is getting the value however it is not setting it to my variable and returning it. what am I doing wrong here?
GetDepartmentID is called with a value of 1. It goes to the controler, the controller returns the departmentID which is 1.
console.log("Inside-DepartmentID " + data) in the console this shows 1 so I know the data is being returns from the controller.
I then assign data to departmentID. Return it. Then my outer function tries to console.log the return and it is undefined. I don't get it.
The .change function calls the GetdepartmentID(1);
function GetDepartmentID(functionID) {
var departmentID;
jQuery.getJSON("/MasterList/GetDepartmentID/" + functionID, null, function (data) {
console.log("Inside-DepartmentID " + data)
departmentID = data;
});
return departmentID;
}
jQuery('#functionID').change(function () {
var functionID = jQuery(this);
//console.log(functionID.val());
var value = GetDepartmentID(functionID.val());
console.log("test " + value);
//GetOwnerList(value);
});
You can try this way to process the data returned back from AJAX call.
function processResults(departmentID)
{
console.log("test " + departmentID);
GetOwnerList(departmentID);
// Someother code.
}
function GetDepartmentID(functionID, callBack) {
jQuery.getJSON("/MasterList/GetDepartmentID/" + functionID, null, function (data) {
console.log("Inside-DepartmentID " + data)
callBack(data); //Invoke the callBackhandler with the data
});
}
jQuery(function(){
jQuery('#functionID').change(function () {
var functionID = jQuery(this);
//console.log(functionID.val());
GetDepartmentID(functionID.val(), processResults); // pass function as reference to be called back on ajax success.
});
});
Or just do this way: This is as good as putting all your subsequent processing code inside your getJSON handler.
function processResults(data)
{
//handle the data here.
}
function GetDepartmentID(functionID) {
jQuery.getJSON("/MasterList/GetDepartmentID/" + functionID, null, processResults);
}
jQuery(function(){
jQuery('#functionID').change(function () {
var functionID = jQuery(this);
//console.log(functionID.val());
GetDepartmentID(functionID.val()); // pass function as reference to be called back on ajax success.
});
});