JSON.parse() fails with unexpected token using Songkick API - json

I'm trying to parse a response from the Songkick API with the following in Node:
router.post('/', function(req, res) {
var artist = req.body.artist;
var id;
res.render('artist', { title: 'Artist', artist: artist });
http.request({host: 'api.songkick.com', path: '/api/3.0/search/artists.json?query=' + artist + '&apikey=myAPIKey'}, function(res) {
res.on("data", function(chunk) {
id = JSON.parse(chunk).resultsPage.results.artist[0].id;
console.log(id);
http.request({host: 'api.songkick.com', path: '/api/3.0/artists/' + id + '/gigography.json?apikey=Z2JWQTvgk4tsCdDn'}, function(res) {
res.on("data", function(chunk) {
console.log(JSON.parse(chunk).resultsPage.results);
});
}).end();
});
}).end();
});
However, JSON.parse fails with SyntaxError: Unexpected token t (the last character changes depending on the artist requested).
Here's an example API response.
How can I fix the syntax error?

basically the same as the other answer. you need to concat the chunks of data and register for an end event and do the parsing there.
Here's one I tried and it seems to work as expected.
var http = require('http');
var artist = 'Beatles'
http.request({host: 'api.songkick.com', path: '/api/3.0/search/artists.json?query=' + artist + '&apikey=Z2JWQTvgk4tsCdDn'}, function(res) {
var response_data = '';
var id;
res.on("data", function(chunk) {
response_data += chunk;
});
res.on('end', function(){
id = JSON.parse(response_data).resultsPage.results.artist[0].id;
console.log(id);
http.request({host: 'api.songkick.com', path: '/api/3.0/artists/' + id + '/gigography.json?apikey=Z2JWQTvgk4tsCdDn'}, function(res) {
var inner_data = '';
res.on("data", function(chunk) {
inner_data += chunk;
});
res.on("end", function(){
console.log(JSON.parse(inner_data).resultsPage.results);
});
}).end();
});
}).end();

I would try to concat the string (arriving in chunks) and then use the end event. Like:
router.post('/', function(req, res) {
var artist = req.body.artist;
var id;
var data1 = '';
res.render('artist', { title: 'Artist', artist: artist });
http.request({host: 'api.songkick.com', path: '/api/3.0/search/artists.json?query=' +
artist + '&apikey=myAPIKey'}, function(res) {
res.on("data", function(chunk) {
data1 += chunk;
});
res.on('end', function(){
id = JSON.parse(data1).resultsPage.results.artist[0].id;
console.log(id);
var data2 = '';
http.request({host: 'api.songkick.com', path: '/api/3.0/artists/' + id + '/gigography.json?apikey=Z2JWQTvgk4tsCdDn'}, function(res) {
res.on("data", function(chunk) {
data2 += chunk;
});
res.on('end', function(){
console.log(JSON.parse(data2).resultsPage.results);
});
}).end();
});
}).end();
});
Basically, it is using data1 and data2 as buffers and calls your function only when all data has arrived.

Related

Cordova GeoLocation not applying lat long to json get

I'm using the Cordova Geolocation plugin to get the users lat and long data. The intention is use that lat and long and apply it to an api call I'm making to Breezometer. Unfortunately my code is is not working correctly. Can someone let me know what im missing here:
.controller('GeoCtrl', function($cordovaGeolocation, $scope, $http) {
var posOptions = {timeout: 10000, enableHighAccuracy: false};
$cordovaGeolocation
.getCurrentPosition(posOptions)
.then(function (position) {
var lat = position.coords.latitude
var long = position.coords.longitude
$scope.result = "";
$http.get('https://api.breezometer.com/baqi/?lat='+ lat + 'lon=-' + long + '&key=c329a5b015f442748e088cfd13726267')
.success(function(data, status, headers,config){
console.log('data success');
console.log(data); // for browser console
$scope.result = data; // for UI
})
.error(function(data, status, headers,config){
console.log('data error');
})
.then(function(result){
things = result.data;
});
}, function(err) {
// error
});
var watchOptions = {
frequency : 1000,
timeout : 3000,
enableHighAccuracy: false // may cause errors if true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
// error
},
function(position) {
var lat = position.coords.latitude
var long = position.coords.longitude
});
watch.clearWatch();
// OR
$cordovaGeolocation.clearWatch(watch)
.then(function(result) {
// success
}, function (error) {
// error
});
})
The url for your http request is wrong.
Try the following,
$http.get(https://api.breezometer.com/baqi/?lat='+ lat + '&lon='+ long +'&key='+ key)
You have miised & in between lat and lon. And lon need not be prefixed with -
Example:
https://api.breezometer.com/baqi/?lat=13.082680199999999&lon=80.2707184&key=c329a5b015f442748e088cfd13726267
Click here to view the results.

Gulp - Unexpected character '#' (1:0) while parsing style\main.scss

I have gulp installed and this is the error that I get. Can someone help me out please?
I have tried deleting the node_modules and did the npm-install. But it still doesnt work.
This is how my gulpfile looks like.
var gulp = require('gulp');
var gutil = require('gulp-util');
var browserify = require('browserify');
var babelify = require('babelify');
var scssify = require('scssify');
var source = require('vinyl-source-stream');
var path = require('path');
var spawn = require('child_process').spawn;
var gls = require('gulp-live-server');
var commandLineArgs = require('command-line-args');
var sass = require('gulp-sass') ;
var notify = require("gulp-notify") ;
var bower = require('gulp-bower');
var runSequence = require('run-sequence');
var lodash = require('lodash');
var config = {
sassPath: './gssp/client/style',
bowerDir: './bower_components'
};
function onError(error) {
gutil.log(error.message);
console.log(error.toString());
}
var cli = commandLineArgs([
{ name: 'packages', alias: 'p', type: String, defaultValue: [""], multiple:true }
]);
var options = cli.parse();
gulp.task('bower', function() {
return bower()
.pipe(gulp.dest(config.bowerDir))
});
gulp.task('icons', function() {
return gulp.src(config.bowerDir + '/font-awesome/fonts/**.*')
.pipe(gulp.dest('./dist/fonts'));
});
gulp.task('embeddedIcons', function() {
return gulp.src('./gssp/src/leafs/icon/fonts/**.*')
.pipe(gulp.dest('./dist/src/leafs/icon/fonts'));
});
gulp.task('css',['bower'], function() {
return gulp.src(config.sassPath + '/*.scss')
.pipe(sass({
outputStyle: 'compressed',
includePaths: [
'./gssp/client/style',
config.bowerDir + '/bootstrap-sass/assets/stylesheets',
config.bowerDir + '/font-awesome/scss',
]
})
.on('error', sass.logError))
.pipe(gulp.dest('./dist/css'));
});
gulp.task('runLiveServer', function () {
var server = gls.new(['gssp/index.js', options.packages.join(" ")]);
server.start();
gulp.watch(['./core/**/*.js','./gssp/**/*.scss'], ['build']);
gulp.watch(['./dist/bundle.js'], function (file) {
server.notify.apply(server, [file]);
});
});
gulp.task('copyStatics', function() {
return gulp.src('./core/server/public/**/*.*')
.pipe(gulp.dest('./dist'));
});
gulp.task('build',['copyStatics', 'icons', 'embeddedIcons', 'css'], function () {
return browserify({
entries: './gssp/client/index.js',
extensions: ['.jsx', '.js'],
debug: true
})
.transform("babelify", {presets: ["es2015", "react", "stage-0"]})
.bundle()
.on('error', onError)
.pipe(source('bundle.js'))
.pipe(gulp.dest('./dist'));
});
gulp.task('run-wrapper', function(done) {
var server = spawn('node', ['serviceWrapper.js'], {stdio: ['inherit']});
server.stderr.on('data', function(data){
process.stderr.write(data);
});
server.stdout.on('data', function(data) {
process.stdout.write(data);
});
server.unref();
});
gulp.task('run', function(done) {
console.log(lodash.concat);
var child = spawn('node', lodash.union(['gssp/index.js'], options.packages), {stdio: ['inherit']});
child.stderr.on('data', function(data){
process.stderr.write(data);
});
child.stdout.on('data', function(data) {
process.stdout.write(data);
});
});
gulp.task('watch', function() {
gulp.watch('./gssp/src/**/*.{js,jsx}', ['build']);
gulp.watch('./gssp/src/**/*.scss', ['build']);
});
gulp.task('serve', function(done) {
runSequence('build', ['run-wrapper', 'runLiveServer'],done)
});
gulp.task('start', function(done) {
runSequence('build', ['run-wrapper', 'run'], done);
});
gulp.task('default', ['start']);
This is how my bower file looks like.
{
"name": "gssp-sales",
"main": "index.js",
"version": "0.6.0",
"authors": [
"Vamshi Gudipati"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"bootstrap-sass": "bootstrap-sass-official#~3.3.6",
"font-awesome": "fontawesome#~4.5.0"
}
}
I have gulp installed and this is the error that I get. Can someone help me out please?
I have tried deleting the node_modules and did the npm-install. But it still doesnt work.
This is how my gulpfile looks like
Open up your font-awesome.css file in dist/css and see in the first block #font-face where the src is pointing to. Make sure it is pointing to the correct directory where you have extracted the font-awesome fonts and the error will go away.
For me I had to do something like this in my gulpfile:
gulp.task('build-fonts', function(){
return gulp.src(config.bowerDir + '/font-awesome/fonts')
.pipe(gulp.dest('./dist/fonts'));
})

Center map on user's location (Google Maps API v3)

I've looked a lot of various other reports about this problem, but I can't find the solution to get the location of user.
Here is my code:
<script src='https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true'>
</script>
<script>
// prepare variables
var main = document.getElementById('main');
// async XHR request
var xhReq = new XMLHttpRequest();
xhReq.open('GET','../data/data.json', true);
xhReq.onload = function (e) {
if ((xhReq.readyState === 4) && (xhReq.status === 200)) {
// prepare external data
var data = JSON.parse(xhReq.responseText);
// prepare map
var map;
// var bounds = new google.maps.LatLngBounds();
var mapOptions = {
zoom: 15,
center: new google.maps.LatLng(54.6867151,25.2803843)
};
map = new google.maps.Map(main,mapOptions);
// add all data to the map
for(i=0;i<data.length;i++){
// loc = new google.maps.LatLng(data[i].lat,data[i].lng);
// bounds.extend(loc);
window['marker'+i] = new google.maps.Marker({
position: new google.maps.LatLng(data[i].lat,data[i].lng),
map: map,
title: data[i].name,
articles: data[i].articles
}
);
// add onClick function
google.maps.event.addListener(window['marker'+i], 'click', function() {
// magic should be here
var data = this.articles;
var list = document.getElementById('list');
var main = document.getElementById('main');
list.innerHTML = '';
list.style="width:25%;";
for(i=0;i<data.length;i++){
list.innerHTML += '<a href="' + data[i].url + '" target="_blank"><div class="listImg" style="background-image:url(' + data[i].img + ');"><\/div><span class="topic">(' + data[i].topic + ')<\/span> <h1>' + data[i].name + ' <\/h1><span class="date">(' + data[i].date + ')<\/span><\/a>';
};
});
};
// recenter + rezoom
// map.fitBounds(bounds);
// map.panToBounds(bounds);
};
};
xhReq.send(null);
</script>
It sets the center of map to exact coordinates which are in code.
Thanks for your support.
English isn’t my first language, so please excuse any mistakes.
Getting the user location is a browser feature that most modern browsers support. However, you still need to test for the ability to get the location in your code.
if (navigator.geolocation) { // test for presence of location feature
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
map.setCenter(initialLocation);
}, function() {
console.log('user denied request for position');
});
} else {
console.log('no geolocation support');
}

how to upload a file using angular js and html only to my local path

I tried some code in tutorialpoint and other sites. while clicking upload button it's not storing to my local folder named fileUpload
js file:
var myApp = angular.module('myApp', []);
myApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload";//created local folder named as fileUpload in same path where this files or found.
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
html file :
<html>
<head>
<script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="upload.js"></script>
</head>
<body ng-app = "myApp">
<div ng-controller = "myCtrl">
<input type = "file" file-model = "myFile"/>
<button ng-click = "uploadFile()">upload me</button>
</div>
please help me to solve this issue.

Calling multiple JSON data with Jquery Deferred

I am trying to get multiple JSON data with deferred object. I have JSON files for individual days. In each individual day, I have data for points, lines and polygons. I have jQueryUI Sliders to visualise for individual days. For example, if the slider has value of 1, only the day1 data (points, lines and polygons) need to be visualised, and for day2, all points, lines and polygons relating to day2 only should be visualised and so on.
I don't know what is problem with my code but it is not serving the required data. Latest data/merged data is shown.
Help me out here.
$(document).ready(function () {
var map = L.map("map", {
center: [27.6419412, 85.1224152],
zoom: 13,
doubleClickZoom: true
});
L.tileLayer('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
L.control.scale().addTo(map);
var markerCluster = L.markerClusterGroup({
showCoverageOnHover: false
});
function TableContent(jsonData) {
var content = $('<div></div>').addClass('table-content');
for (row in jsonData) {
var tableRow = $('<div></div>').addClass('table-row').append(function () {
var key = row;
if (!(key === "#uid" || key === "#changeset" || key === "#version" || key === "#timestamp" || key === "#id")) {
return jsonData[row] ? $("<div></div>").text(key).append($("<div></div>").text(jsonData[row])) : "";
}
});
tableRow.prependTo(content).addClass(row);
}
return $(content)[0];
}
function Table(json) {
return $('<div></div>').append($('<div class="title"></div>').text(json.type)).addClass('table-container').append(new TableContent(json.data));
}
var pointBuild = L.geoJson(null, {
pointToLayer: function (feature, latlng) {
var deferred = $.Deferred();
marker = L.marker(latlng, {
icon: L.icon({
iconUrl: 'img/marker.png',
iconSize: [30, 30],
iconAnchor: [15, 15]
}),
riseOnHover: true,
title: "This is a Point feature. Click to have a look at some of its attributes"
});
markerCluster.addLayer(marker);
deferred.resolve();
map.fire('cluster-hover');
return marker;
},
onEachFeature: function (feature, layer) {
var popup = L.popup();
layer.on('click', function (e) {
var deferred = $.Deferred();
popup.setLatLng(e.latlng);
popup.setContent(new TableContent(feature.properties));
popup.openOn(map);
deferred.resolve();
});
}
});
var myStyle = {
weight: 2,
opacity: 1,
color: '#FF0000',
dashArray: '3',
fillOpacity: 0.3,
fillColor: '#FA8072'
};
var wayBuild = L.geoJson(null, {
style: myStyle,
onEachFeature: function (feature, layer) {
var popup = L.popup();
layer.on('click', function (e) {
var deferred = $.Deferred();
popup.setLatLng(e.latlng);
popup.setContent(new TableContent(feature.properties));
popup.openOn(map);
deferred.resolve();
});
}
});
function pointLinePolygon(receivedPoints, receivedLines, receivedPolygon, day) {
var points_, lines_, polygon_;
var deferredPoint = $.Deferred();
var deferredLine = $.Deferred();
var deferredPolygon = $.Deferred();
$.getJSON(receivedPoints, function (data) {
setTimeout(function () {
pointBuild.addData(data);
points_ = markerCluster;
deferredPoint.resolve();
}, 0);
});
$.getJSON(receivedLines, function (data) {
setTimeout(function () {
lines_ = wayBuild.addData(data);
deferredLine.resolve();
}, 0);
});
$.getJSON(receivedPolygon, function (data) {
setTimeout(function () {
polygon_ = wayBuild.addData(data);
deferredPolygon.resolve();
}, 0);
});
$.when(deferredPoint, deferredLine, deferredPolygon).done(function () {
var featureGroup = L.layerGroup([points_, lines_, polygon_]);
featureGroup.addTo(map);
$.map(wayBuild._layers, function (layer, index) {
$(layer._container).find("path").attr("title", "This is a way feature. Click to have a look at some of its attributes.");
});
});
}
map.on('cluster-hover', function () {
setTimeout(function () {
$("#map").find("div.marker-cluster").attrByFunction(function () {
return {
title: "This is a Cluster of " + $(this).find("span").text() + " Point features. Click to zoom in and see the Point features and sub-clusters it contains."
}
});
}, 0);
});
var tooltip = $('<div id="toolTipSlider" />').hide();
$('#slider').slider({
min: 1,
max: 4,
slide: function (event, ui) {
if (ui.value === 1) {
tooltip.text("Day " + ui.value);
$.ajax({
type: 'post',
success: function () {
pointLinePolygon("data/day1/points.geojson", "data/day1/lines.geojson", "data/day1/polygon.geojson", "Day 1");
}
});
}
else if (ui.value === 2) {
tooltip.text("Day " + ui.value);
$.ajax({
type: 'post',
success: function () {
pointLinePolygon("data/day2/points.geojson", "data/day2/lines.geojson", "data/day2/polygon.geojson", "Day 2");
}
});
}
else if (ui.value === 3) {
tooltip.text("Day " + ui.value);
$.ajax({
type: 'post',
success: function () {
pointLinePolygon("data/day3/points.geojson", "data/day3/lines.geojson", "data/day3/polygon.geojson", "Day 3");
}
});
}
else if (ui.value === 4) {
tooltip.text("Day " + ui.value);
$.ajax({
type: 'post',
success: function () {
pointLinePolygon("data/day4/points.geojson", "data/day4/lines.geojson", "data/day4/polygon.geojson", "Day 4");
}
});
}
}
}).find(".ui-slider-handle").append(tooltip).hover(function () {
tooltip.show();
});
});
$.fn.attrByFunction = function (a) {
return $(this).each(function () {
$(this).attr(a.call(this));
});
};
I solved the problem by clearing the map layer every time I am to add new one.
map.eachLayer(function (layer) {
if (layer.feature) {
map.removeLayer(layer);
}
});