$http.get() returns blank data in AngularJS from external source - json

I tried to fetch data from external sources in Angular JS via $http but it returns blank data. The same service when used to fetch data from a local file works perfect.
The code for fetching data from local source:
controllers.controller('listController', ['$scope', '$http',
function($scope,$http) {
var data = null;
$http.get('js/test.json').success(function(data) {
$scope.markers = data.hooks;
});
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 2
};
}]);
The code for fetching data from an external source:
controllers.controller('listController', ['$scope', '$http',
function($scope,$http) {
var data = null;
$http.get('http://115.113.151.200:8081/user/maphook/mobile/generate_list.jsp').success(function(data) {
$scope.markers = data.hooks;
});
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 2
};
}]);
As you can see just the url has changed, in the latter case firebug happens to show the following in the console:
Image
I'm not sure what is wrong. I use the json data to plot points on a google map. The test.json works perfectly. I'm assuming it could either be that external sources of data (domain different than the current) are not allowed, or the Angular goes on to render the google map even before the data is returned from the external source.

The problem is that the external server doesn't allows you to request data.
There is a whole standard shaping this.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
http://enable-cors.org/

You should read on JSONP if you intend to use ajax cross-domain to send and receive json data. It is supported in angular.js, you just need to find an example (Google has loads).
Jsonp is what you need.

Related

Microsoft cognitive services face API call

I've build an application on the Azure (microsoft) emotion API, but that was just merged with their cognitive services face API. I'm using a webcam to send an image (in binary data) to their server for analysis, and used to get an xml in return. (I've already commented out some old code, in this example. Trying to get it fixed).
function saveSnap(data){
// Convert Webcam IMG to BASE64BINARY to send to EmotionAPI
var file = data.substring(23).replace(' ', '+');
var img = Base64Binary.decodeArrayBuffer(file);
var ajax = new XMLHttpRequest();
// On return of data call uploadcomplete function.
ajax.addEventListener("load", function(event) {
uploadcomplete(event);
}, false);
// AJAX POST request
ajax.open("POST", "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=emotion","image/jpg");
ajax.setRequestHeader("Content-Type","application/json");
//ajax.setRequestHeader("Accept","text/html,application/xhtml+xml,application/xml");
ajax.setRequestHeader("Ocp-Apim-Subscription-Key","subscription_key");
ajax.send(img);
}
now I understood from their website the call returns a JSON. But I just can't get it to work. I can see there is data coming back, but how do I even get the JSON out of it. I'm probably missing something essential, and hope someone can help me out. :) the program was working when I could still use the Emotion API.
function uploadcomplete(event){
console.log("complete");
console.log(event);
//var xmlDoc = event.target.responseXML;
//var list = xmlDoc.getElementsByTagName("scores");
console.log(JSON.stringify(event));
A few issues to address:
You'll want to wait for the POST response, not just for the upload
completion.
You'll want to set the content type to be application/octet-stream if you are uploading a binary as you are.
You'll want to set the subscription key to the real value (you probably did before pasting your code here.)
.
function saveSnap(data) {
// Convert Webcam IMG to BASE64BINARY to send to EmotionAPI
var file = data.substring(23).replace(' ', '+');
var img = Base64Binary.decodeArrayBuffer(file);
ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if (ajax.readyState == XMLHttpRequest.DONE) {
console.log(JSON.stringify(ajax.response));
}
}
ajax.open('post', 'https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=emotion');
ajax.setRequestHeader('Content-Type', 'application/octet-stream');
ajax.setRequestHeader('Ocp-Apim-Subscription-Key', key);
ajax.send(img);
}

backbone.js fetch json success will not hit

i use fetch from backbone.js to load a json model but success will not hit.
var DialogModel = Backbone.Model.extend({
url : function() {
return '/messages/getDialog';
},
parse : function(res) {
return res.dialog;
}
});
var DialogView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
var onDataHandler = function() {
this.render();
};
this.model = new DialogModel();
this.model.fetch({ success : onDataHandler});
},
render: function(){
var data = {
dialogModel : this.model
};
var form = new Backbone.Form({
model: data
});
$(this.el).html(form.render().el);
}
});
What happens now:
DialogView initialize is called.
this.model.fetch is called but the onDataHandler function will not be hit if success.
/messages/getDialog throws a json file back.
The json file is loading well as i can see in the network browser.
Thanks for your help!
Oleg
The problem you're having is due to a typical JS gotcha and not related to Backbone itself. Try
var that = this;
this.model.fetch({
success : function () {
that.render();
}
});
The way you're currently passing onDataHandler is problematic as it will cause this to refer to the global object instead of the DialogView, when the function is called.
This fiddle demonstrates the problematic version vs one that works.
(You may also want to take a look at JS strict mode which can shield you from this type of errors.)
Even better is to listen for an event:
this.model.on("sync", this.render).fetch();
I ran across this question while looking for something else, but the currently accepted answer drives me nuts. There's no good reason to be sprinkling this and that all over your code. Backbone (underscore) includes a context parameter that you can bind to.
that = this makes no sense. If you must implement obsolete 2007-era Crockford patterns, then say var self = this. Saying that = this is like saying left = right. Everyone Stop.

Ignore hidden features returned by identifyTask

I am building an app using javascript, google maps v2 and ESRI 10.1.
I have a DynamicMapServiceLayer and a single layer in my ESRI map service. I dynamically show or hide features on the layer using the ESRI setLayerDefinitions function based on filter values selected by the user at runtime.
When the user clicks on the map I use the ESRI IdentifyTask object to find what the user clicked on. I want to show an infowindow for the feature the user clicked on. My code is sort of working but it opens infowindows for features that are filtered out (not visible) on the layer.
How can I check to see if the user clicked on a visible feature and stop opening infowindows for hidden features? Or how can I get IdentifyTask to stop including hidden features in the response object it returns?
This is my identifyParameters task invoke set up
// set the identify parameters
var identifyParameters = new esri.arcgis.gmaps.IdentifyParameters();
identifyParameters.geometry = latLng; // where the user clicked on the map
identifyParameters.tolerance = 3;
identifyParameters.layerIds = [OUTAGES_LAYER];
identifyParameters.layerOption = 'all';
identifyParameters.bounds = map.getBounds();
var mapSize = map.getSize();
identifyParameters.width = mapSize.width;
identifyParameters.height = mapSize.height;
// execute the identify operation
identifyTask.execute(identifyParameters, function(response, error) {
if (hasErrorOccurred(error)) return;
addResultToMap(response, latLng);
});
UPDATE
I have upgraded to Google maps v3. Now the identify parameters support passing layerdef information as follows below. For example I can limit the identify operation to those features where FISCAL_YEAR = 2014. My problem is solved.
function identify(evt) {
dynamicMap.getMapService().identify({
'geometry': evt.latLng,
'tolerance': 3,
'layerIds': [12],
'layerOption': 'all',
'layerDefs': {12 : 'FISCAL_YEAR = 2014'},
'bounds': map.getBounds(),
'width': map.getDiv().offsetWidth,
'height': map.getDiv().offsetHeight
}, function(results, err) {
if (err) {
alert(err.message + err.details.join('\n'));
} else {
addResultToMap(results, evt.latLng);
}
});
}

WFS Layer in OpenLayers queries server for GML data but doesn't display the returned data

I have added a WFS layer to a map and can see (using Fiddler) a request being made to the server for the layer data. The server uses GML as the data format and the data being returned is valid. However, OpenLayers does not display the data. Here is the code that I use.
$(document).ready(
function () {
// allow testing of specific renderers via "?renderer=Canvas", etc
var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
var geographic = new OpenLayers.Projection("EPSG:4326");
var mercator = new OpenLayers.Projection("EPSG:900913");
map = new OpenLayers.Map({
div: "map",
layers: [
new OpenLayers.Layer.WMS("OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{ layers: "basic" }
),
new OpenLayers.Layer.Vector("GML", {
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.WFS({
url: "http://localhost/MapServer/Default.aspx",
featureType: "Layer_ACTIVE",
featureNS: "http://www.tstgis.org/gml",
version: "1.1.0",
geometryName: "line"
}),
renderers: renderer
})
],
zoom: 15
});
var bb = new OpenLayers.Bounds(-179.821327209473, 12.1057098342161, -56.5289154052734, 78.1442901657839);
map.zoomToExtent(bb);
});
This test script is part of an HTML shell that is running under localhost/mapserver, so it rules out the familiar cross-domain issue.
What is going on? Note: the returned data set is pretty big (1.5 MB) and I wonder if that has anything to do with the missing display.
I had no doubt that this was a configuration issue with OpenLayers. From what I knew about OpenLayers, I had it configured properly. Turns out, it is essential, in my case, to set the featurePrefix option. The reason for this is that the namespace and prefix in the XML response (GML) for each FeatureMember Node is used to identify the appropriate reader for the response. By default, the featurePrefix is set to ‘feature’. If the response's namespace + prefix does not match the configuration in OpenLayers, the features are not added to the layer and hence not displayed. In my case, the prefix is set to an empty string as the server does not add a prefix to the response.
Also, setting the geometryName is critical. The default value for geometryName is ‘the_geom’ for WFS version 1.0, and null for higher versions. The geometryName is used by the server to actually locate the features. In my case, geometryName used on the server was "msGeometry".
Here is the working code.
$(document).ready(
function () {
// allow testing of specific renderers via "?renderer=Canvas", etc
var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
var geographic = new OpenLayers.Projection("EPSG:4326");
var mercator = new OpenLayers.Projection("EPSG:900913");
map = new OpenLayers.Map({
div: "map",
layers: [
new OpenLayers.Layer.WMS("OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{ layers: "basic" }
),
new OpenLayers.Layer.Vector("GML", {
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.WFS({
url: "http://localhost/MapServer/Default.aspx",
featureType: "Data_ACTIVE",
version: "1.1.0",
geometryName: "msGeometry",
featurePrefix: ""
}),
renderers: renderer
})
],
zoom: 15
});
var bb = new OpenLayers.Bounds(-179.821327209473, 12.1057098342161, -56.5289154052734, 78.1442901657839);
map.zoomToExtent(bb);
});

Google API 3 expires after some time

I'm using Gmap3-Jquery plugin to generate Google maps in one of my web application.
Currently i downloaded the Google API to my local drive and using the same in my HTML page.
However all the actions working fine for me, but after 3-4 days Google API stops working. If i download the fresh Google API from the same link to my local drive everything works fine. What may be the cause for such problem? Is it because of API Key? or is it because i downloaded to my local drive and referencing it from locally?
But I'm downloading Google maps API3, which doesn't require API key.
Here is the code:
<script src="/site_media/js/google-map.js" type="text/javascript"></script>
<script type="text/javascript" src="/site_media/js/gmap3.js"></script>
<script type="text/javascript">
$(function(){
$('#facility_map').gmap3(
{
action:'init',
options:{
center:[26.327475, 50.20134],
zoom: 18,
mapTypeId: google.maps.MapTypeId.HYBRID
}
},
{
action:'getRoute',
options:{
origin:['26.327475', '50.20134'],
destination:['{{facility.latitude}}', '{{facility.longitude}}'],
travelMode: google.maps.DirectionsTravelMode.DRIVING
},
callback: function(results)
{
if (!results) return;
$(this).gmap3(
{
action:'addDirectionsRenderer',
options:{
preserveViewport: true,
directions:results
}
});
}
},
{
action:'getDistance',
options:{
origins:[['26.327475', '50.20134']],
destinations:[['{{facility.latitude}}', '{{facility.longitude}}']],
travelMode: google.maps.TravelMode.DRIVING
},
callback: function(results)
{
var html = '';
if (results)
{
for (var i = 0; i < results.rows.length; i++)
{
var elements = results.rows[i].elements;
for(var j=0; j<elements.length; j++)
{
switch(elements[j].status)
{
case google.maps.DistanceMatrixStatus.OK:
html += results.destinationAddresses[j]+" -<b> "+elements[j].distance.text + ' (' + elements[j].duration.text + '</b>)<br />';
break;
case google.maps.DistanceMatrixStatus.NOT_FOUND:
html += 'The origin and/or destination of this pairing could not be geocoded<br />';
break;
case google.maps.DistanceMatrixStatus.ZERO_RESULTS:
html += 'No route could be found between the origin and destination.<br />';
break;
}
}
}
}
else
{
html = 'error';
}
$('#distance_msg').html("Distance From Rezayat Head Office Khobar to "+html);
}
}
);
});
</script>
Are you saving the following file to your hard drive/web app:
http://maps.google.com/maps/api/js?sensor=false
If so, then the answer to your question...
or is it because i downloaded to my local drive and referencing it
from locally?
...is Yes.
That file you are referencing is cached, so it is always changing. I've never used the jQuery maps plugin that you mentioned above (it looks really cool, though!), but in looking at their API it mentions that you should call that script from Google, and not store it directly.
Also, remember, let Google handle that JS load and bandwidth for you, and try to stay away from storing that locally. The API could change, and with your cached version, your map might break because it's not loading the most recent version.
I'll also add one more thing: let Google load your jQuery, too - people using the site will have a better experience. This article will explain why more.