Imgur API http post image with angular JS - javascript

my angular js code is failing to upload an image with the imgur API.
angular js http post method
angular js http post method
HTML:
<!doctype html>
<html ng-app="stalkcalibrator">
<head>
<title>Corn Stalk Calibrator</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="style/style.css"/>
<script src="angular.js"></script>
<script src="controllers.js"></script>
</head>
<body ng-controller="adminController">
<h1 id="title">Calibrator - Admin Upload</h1>
<!-- back to admin home -->
<div id="back">Admin Home</div>
<!-- form used to upload one or more images -->
<form>
<!-- button allows user to browse local directory for image -->
<!-- ng-model saves image var in array -->
Upload image <input type="file" ng-model="img" accept="image/*" id="file" />
<!-- executes js upload function with uploaded images -->
<button><a ng-click="upload()">Submit</a></button>
<p ng-model="num">{{num}}</p>
</form>
</body>
</html>
Here's my JS:
var stalkcalibrator = angular.module('stalkcalibrator', []);
stalkcalibrator.controller('adminController', function($scope){
//array of data for each stalk. PULL FROM JSON FILE!
$scope.stalks = [{id:1, name:2, thumbnail:3, note:4}, {id:9, name:10, thumbnail:11, note:12}, {id:5, name:6, thumbnail:7, note:8}];
//array of image uploads
$scope.img;
$scope.num = 1;
function getStalks($scope){
}
$scope.upload = function() {
$http({
headers: {'Authorization': 'Client-ID 010fe699c18e3c9'},
url: 'https://api.imgur.com/3/',
type: 'POST',
data: {'image': $scope.img}
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.num = 2;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.num = 3;
});
//adds image data to JSON file
//_TODO_
};
});
Thanks!
EDIT: neither errorCallback nor successCallback is being called back.

I would change your code like this:
angular.module('stalkcalibrator', []) //best practise is not to declare a variable to contain this
.controller('adminController',['$scope','$log','$http', function($scope,$log,$http){ // safe dependency injection
var self = this; //self will contain the data from the controller. I dislike to put all into the scope.
//array of data for each stalk. PULL FROM JSON FILE!
self.stalks = [{id:1, name:2, thumbnail:3, note:4}, {id:9, name:10, thumbnail:11, note:12}, {id:5, name:6, thumbnail:7, note:8}];
//array of image uploads
self.img;
self.num = 1;
self.getStalks = function($scope){};
self.upload = function() {
$http({
headers: {'Authorization': 'Client-ID 010fe699c18e3c9'},
url: 'https://api.imgur.com/3/',
type: 'POST',
data: {'image': self.img}
}).then(function successCallback(response) {
self.num = 2;
$log.log('called and successful', response);
}, function errorCallback(err) {
self.num = 3;
$log.log('called but error', err);
});
};
}]);
Then the html:
<body ng-controller="adminController as ac">
<h1 id="title">Calibrator - Admin Upload</h1>
<!-- back to admin home -->
<div id="back">Admin Home</div>
<!-- form used to upload one or more images -->
<form>
Upload image <input type="file" ng-model="ac.img" accept="image/*" id="file" />
<!-- executes js upload function with uploaded images -->
<button ng-click="ac.upload()">Submit</button>
<p ng-bind="ac.num"></p>
</form>
</body>
Try this, I think the problem might have been in
<button><a ng-click="upload()">Submit</a></button>
You were clicking on the button and not on the text (that was the actual anchor that was able to call the upload function).
With this we should at least be able to see something in console

Resolved. It turns out that self.img was the wrong file type for the Imgur API. Had to convert to base64 and make edits suggested by #Gianmarco

Related

HTML page not rendering from Flask after AJAX call

I want to send a JavaScript variable with a image that a user will upload to my Flask file where processing will be done. So I am using Formdata and a AJAX call for the same. But after the data and image is received in flask and processing is done, I am unable to render a HTML page in flask which will display the processed image .
Java Script Code :
formdata = new FormData();
jQuery("#image_to_upload").on("change", function() { // On Change Of image upload
var file = this.files[0];
if (formdata) {
formdata.append("file", file);
formdata.append("array", filtersActive);
jQuery.ajax({
url: "/object-detect-uploader",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success:function(){}
});
}
});
Flask Code :
#app.route("/object-detect-uploader", methods = ['GET', 'POST'])
def upload_object_detection():
detect_objs = request.values['array'].split(",")
d_array= [0 for i in range(6) ]
for i in detect_objs:
d_array[int(i)] = 1
for upload in request.files.getlist("file"):
filename = upload.filename
# This is to verify files are supported
ext = os.path.splitext(filename)[1]
if (ext == ".jpg") or (ext == ".png"): #File extention check
print("File supported moving on...")
ans=(object_detection_module.object_detection(upload,d_array))
else:
render_template("Error.html", message="Files uploaded are not supported...")
print("Rendering")
return render_template("index.html", result = ans)
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<br>
<br>
<h1><center>Output</h1></center>
<br>
<img src="data:image/png;base64, {{result[0]}}" >
<br>
<br>
<h2> No of objects = {{ result[1] }}</h2>
</body>
</html>
An Ajax call is an asynchronous request initiated by the browser that does not reload the page when it receives the server response.
IMO, since you want to render the template, you should not use AJAX, just use a normal <form> element or create a form programmatically, fill the data, then submit with jQuery('selector').submit().

ajax not loading/retrieving data

I'm doing the FreeCodeCamp course and i'm trying to build a weather app. I found a nice tutorial on how to get the latitude and longitude with geolocation. But now when I try and run the app it doesn't seem to be retrieving the ajax data for me to parse through. I was trying locally and moved it to hosting thinking that might have been it but now I just get a weird error on line one of my html and i don't see anything wrong. Thanks guy here is the code and it's live on weatherapp.boomersplayground.com
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Weather APP</title>
<link rel="stylesheet" href="style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src='script.js'></script>
</head>
<body>
<div id="forecast">
<h1>Weather at <span id="location"> </span></h1>
<!-- <div id="imgdiv">
<img id="img" src=""/> -->
</div>
<p>It is currently <span id="temp"> </span>F with <span id="desc"> </span></p>
<p>Wind: <span id="wind"></span></p>
</div>
</body>
</html>
script.js
$(document).ready(function(){
var Geo = {};
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(success,error);
} else {
alert('Geolocation is not supported');
}
function error(){
alert("That's weird! We couldn't find you!");
}
function success(position){
Geo.lat = position.coords.latitude;
Geo.lng = position.coords.longitude;
}
var key = 'c7e3b3ac66e765aa';
var Weather = "http://api.wunderground.com/api/"+ key +"/geolookup/conditions/q/" + Geo.lat + "," + Geo.lng + ".json";
$.ajax({
url : Weather,
dataType : 'jsonp',
success : function(data) {
var location =data['location']['city'];
var temp = data['current_observation']['temp_f'];
var img = data['current_observation']['icon_url'];
var desc = data['current_observation']['weather'];
var wind = data['current_observation']['wind_string'];
}
})
//setting the spans to the correct parameters
$('#location').html(location);
$('#temp').html(temp);
$('#desc').html(desc);
$('#wind').html(wind);
// filling the image src attribute with the image url
// $('#img').attr('src', img);
});
You use the variables initialised at the AJAX response outside of the success callback. You should use them inside the callback, since they're created asynchronously:
$.ajax({
url : Weather,
dataType : 'jsonp',
success : function(data) {
var location =data['location']['city'];
var temp = data['current_observation']['temp_f'];
var img = data['current_observation']['icon_url'];
var desc = data['current_observation']['weather'];
var wind = data['current_observation']['wind_string'];
$('#location').html(location);
$('#temp').html(temp);
$('#desc').html(desc);
$('#wind').html(wind);
}
});
Because you are treating an Asynchronous call as a synchronous one. The Ajax call needs to be in the success callback of getCurrentPosition. You are building the Ajax url before the at and lng is returned.

Adding images from url to a zip file using jsZip

I am trying to create a zip file using jsZip . The contents of the zip file are images from the web.
I have created the following code. But when i run it all am getting is an empty zip file of 22kb.
<html>
<body>
<script type="text/javascript" src="jszip.js"></script>
<script type="text/javascript" src="FileSaver.js"></script>
<script type="text/javascript" src="jszip-utils.min.js"></script>
<script>
var imgLinks = ["url1", "url2", "url3"];
function create_zip() {
var zip = new JSZip();
for (var i = 0; i < imgLinks.length; i++) {
JSZipUtils.getBinaryContent(imgLinks[i], function(err, data) {
if (err) {
alert("Problem happened when download img: " + imgLink[i]);
console.erro("Problem happened when download img: " + imgLink[i]);
deferred.resolve(zip); // ignore this error: just logging
// deferred.reject(zip); // or we may fail the download
} else {
zip.file("picture" + i + ".jpg", data, {
binary: true
});
deferred.resolve(zip);
}
});
}
var content = zip.generate({
type: "blob"
});
saveAs(content, "downloadImages.zip");
}
</script>
<br/>
<br/>
<center>
Click the button to generate a ZIP file
<br/>
<input id="button" type="button" onclick="create_zip()" value="Create Zip" />
</center>
</body>
</html>
(url1 , url2 and url3 replaced by image urls i want to download).
Why am i getting these empty zip files?
JSZipUtils.getBinaryContent is asynchronous : the content will be added after the call to zip.generate(). You should wait for all images before generating the zip file.
Edit :
If the files you are loading are on a different server, this server need to send additional HTTP headers, like Access-Control-Allow-Origin: server-hosting-the-page.com. The Firefox or Chrome debug console will show an error in that case. The js library can't detect a CORS issue (see here) and will trigger a success with an empty content.

Performing 2 successive tasks when a HTML form is submitted (using Ajax and a server made with Express in Node.js)

I have an input form in a HTML file:
<form id="urlarticle">
<input type='text' name='thislink'>
<input type='submit' value='Select'>
</form>
I want, when the submit button is clicked, 2 things to happen, in this order:
TASK 1: Make a POST request to a server, in order to enter new data in a database. Actually it is already working with the following code on the front-end:
<script type='application/javascript'>
$("#urlarticle").submit(function() {
$.ajax({
type: "POST",
url: "/selection/yes",
data: $("#urlarticle").serialize(),
success: function(data)
{alert(data);
}
});
return false;
});
</script>
...and with the following code on the back-end (server made with Express in Node.js):
app.post('/selection/yes', function(req, res) {
link = req.body.thislink;
// part omitted here: function that do several things and then save some data to a database
});
TASK 2: Open a new window, rendered with an EJS view following a GET request on the server-side. TASK 2 has to be performed after TASK 1, because it uses the data saved in the database by TASK 1.
The code on the front-end should look like this:
<script type='application/javascript'>
$("#urlarticle").submit(function() {
var linkValue = $('input[name="thislink"]').val();
window.open('/selection/yes/?value='+linkValue);
});
</script>
...and the task is ready to be handled on the back-end:
app.get('/selection/yes/', function(req, res) {
var thislink = req.param("value");
// parts omitted here
res.render('selection_form.ejs');
});
});
But how can I make this TASK 2 to be executed only after TASK 1 is done? Thank you for your help!
I've created a sample NodeJS application that uses a lot of the same concepts (using Express and some jQuery on the client-side).
WORKING EXAMPLE: http://runnable.com/U3JEKcrGzPc1V8eQ/promises-w-bluebird-for-node-js-and-express
Using a basic Express application where an initial form is rendered using EJS (this is the GET request on /). Form submissions return a POST request to the same URL and are handled with a 2s delay to simulate a database action.
/**
* Create a global storage variable as a example of an
* attached local database
*/
GLOBAL.linkStorage = [];
app.route('/')
.post(function(req, res){
console.log("Submission: " + req.body);
GLOBAL.linkStorage.push(req.body.link);
renderDelayedResponse(res);
})
.get(function(req, res){
res.render('form.ejs');
});
app.route('/2')
.get(function(req, res) {
// No need to pass in GLOBAL.linkValue since it's checked automatically
res.render('submission.ejs');
});
/**
* Delay the response by a few seconds to simulate a database
* create/update action
*/
function renderDelayedResponse(respWriter) {
setTimeout(function() {
GLOBAL.viewCount++;
respWriter.send('Action Completed');
}, 2000);
}
There are going to be problems with calling window.open() after an asynchronous action, the popup blocker fires in all cases through my tests. To workaround this, you can see that the example has an embedded IFRAME that refreshes (after the 2 second database save completes) and displays the submitted value.
The complexity is mostly handled through jQuery where the IFRAME refresh occurs after we know that the POST request has submitted:
<!doctype html>
<html>
<head>
<style>
.busy {
cursor: wait !important;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
<script type="text/javascript">
$('document').ready(function () {
function refreshViewer() {
window.open("/2", "viewer");
document.getElementById('submissionFrame').contentWindow.location.reload(true);
}
$('form input#submitLink').on('click', function () {
var linkValue = $('input#link').serialize();
$('body').addClass('busy');
$.post('/', linkValue)
.done(function(data) {
$('body').removeClass('busy');
$('input#link').val('');
refreshViewer();
});
return false;
});
});
</script>
</head>
<body>
<div class="container">
<form id="urlarticle" method="POST">
<input type="text" name="link" placeholder="Link" id="link" />
<input type="button" value="Submit" id="submitLink" />
</form>
<iframe id="submissionFrame" src="/2" seamless="seamless" width="50%" style="margin-top:100px">
</iframe>
</div>
</body>
</html>

Google+ api OAuth 2.0 : how to access token object 'authResult' from .js file

I have a HTML/CSS/JS app using Jquery Mobile, in which I would like to create a sign-up page.
The function signinCallback in the .html perfectly finds the variable called authResult (OAuth 2.0 Token Object), but in the .js authResult is undefined and therefore the function signinCallback doesn't work (see info on this function here : https://developers.google.com/+/web/signin/disconnect) nor other api's methods like gapi.auth.getToken();.
I get the following errors from the .js file :
ReferenceError: gapi is not defined
ReferenceError: authResult is not defined
Can you help me figure out why ?
Thanks.
The .html:
<!-- SIGN-IN PAGE -->
<div id="signin-page" data-role="page" data-add-back-btn="true" data-back-btn-text="Back">
<header data-role="header">
</header>
<div id="contentsignin" data-role="content">
<script type="text/javascript">
function signinCallback(authResult) {
console.log(' --signinCallback in script in .html');
if (authResult['status']['signed_in']) {
} else {
}
}
</script>
<span id="signinButton">
<span
class="g-signin"
data-callback="signinCallback"
data-clientid="myclientid"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login">
</span>
</span>
<button type="button" id="revokeButton">
Revoke token...
</button>
</div>
</div>
...
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
The .js:
var testtest = gapi.auth.getToken();
$('#revokeButton').click(disconnectUser);
console.log(authResult);
function disconnectUser(authResult) {
var access_token = authResult['access_token'];
var revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token=' +
access_token;
// Perform an asynchronous GET request.
$.ajax({
type: 'GET',
url: revokeUrl,
async: false,
contentType: "application/json",
dataType: 'jsonp',
success: function(nullResponse) {
// Do something now that user is disconnected
// The response is always undefined.
document.getElementById('loginstatusin').setAttribute('style', 'display: none');
document.getElementById('loginstatusin').setAttribute('style', 'display: block');
},
error: function(e) {
// Handle the error
}
});
}
Its a little bit late answer but I think you need to first download js script which contains authResult and then download your own .js file so that when code in your .js file is executing, authResult related code is already downloaded and present for your code.
<script src="path\to\js_file\containing\authResult"></script>
<script src="path\to\your\js_file.js"></script>

Categories

Resources