how to properly handle variable scope in AngularJS - javascript

In my AnlgularJS controller, my first order of business is to determine if the app is running in dev, or test.
For that purpoer, I make a call to an api, an an answer back (that part is verified to work).
Depending on the environment, I need to set the value for the $scope.uploadUrl, so my file uploader directive would know which url is to target for its file uploads.
For some reason, by the time the uploader is executed, that url value is lost.
Here is the relevant part of my controller:
$scope.uploadUrl = '';
console.log('This is FileUploadController');
function getEnvironment (){
$http.get('/environment').success(function(response) {
$scope.currentEnvironment = response.environment;
if(response.environment === 'test'){
$scope.uploadUrl = 'http://test_url:3001/api/files';
}
if(response.environment === 'dev'){
$scope.uploadUrl = 'http://dev_url:3000/api/files';
}
console.log('Current Environment is: ' + $scope.currentEnvironment
+ ' so the uploadUrl should be: ' + $scope.uploadUrl);
});
}
getEnvironment();
var selectedCategory;
var selectedDataVersion;
var uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
What is the proper way to re-structure this code, to make the value, set within my getEnvironment function to live long enough?

For some reason, by the time the uploader is executed, that url value is lost.
Not really, actual reason is by the time uploaded is executed, url value has not been assigned yet because the operation that assigns the value is async (AsycJAX) in nature.
So basically you need to wait for that operation to complete, you can do so by utilizing the promise returned by the operation.
//return promise from the function
function getEnvironment (){
return $http.get('/environment')....
}
//Make a call chain it through and register runUploader
getEnvironment().then(runUploader);
var selectedCategory;
var selectedDataVersion;
function runUploader(){
var uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
}

I don't think your problem has to do with the life time. The problem I see there is that, when you create your uploader, the AJAX call has not returned yet.
Try this:
$scope.uploadUrl = '';
$scope.uploader;
var selectedCategory;
var selectedDataVersion;
var uploader;
console.log('This is FileUploadController');
function initUploader()
{
uploader = $scope.uploader = new FileUploader({
//url: 'http://dctool-lnx.cloudapp.net:3001/api/files',
url: $scope.uploadUrl,
tabName: 'sheet1'
});
}
function getEnvironment (){
$http.get('/environment').success(function(response) {
$scope.currentEnvironment = response.environment;
if(response.environment === 'test'){
$scope.uploadUrl = 'http://test_url:3001/api/files';
}
if(response.environment === 'dev'){
$scope.uploadUrl = 'http://dev_url:3000/api/files';
}
initUploader();
console.log('Current Environment is: ' + $scope.currentEnvironment
+ ' so the uploadUrl should be: ' + $scope.uploadUrl);
});
}
getEnvironment();

Related

How to use microsoft cognitive api for emotion detection in faces?

I am trying to detect emotions in faces from an image uploaded. I can't seem to find any example code for emotion detection.
https://azure.microsoft.com/en-us/try/cognitive-services/my-apis/?apiSlug=face-api&country=Canada&allowContact=true
I found this
https://learn.microsoft.com/en-us/azure/cognitive-services/emotion/quickstarts/javascript
but the url endpoint doesn't work. I then tried regular face api, but even that I get resource not found.
Does anyone know what's going one?
Thanks
var FACE = new function () {
this.listen = function() {
var camera = document.getElementById('camera');
camera.addEventListener('change', function(e) {
var imageFile = e.target.files[0];
var reader = new FileReader();
var fileType;
//wire up the listener for the async 'loadend' event
reader.addEventListener('loadend', function () {
//get the result of the async readAsArrayBuffer call
var fileContentArrayBuffer = reader.result;
sendImage(fileContentArrayBuffer, fileType);
});
if (imageFile) {
//save the mime type of the file
fileType = imageFile.type;
//read the file asynchronously
reader.readAsArrayBuffer(imageFile);
}
});
function sendImage(fileContentArrayBuffer, fileType) {
$.ajax({
// NOTE: You must use the same location in your REST call as you used to obtain your subscription keys.
// For example, if you obtained your subscription keys from westcentralus, replace "westus" in the
// URL below with "westcentralus".
url: "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/",
beforeSend: function(xhrObj){
// Request headers, also supports "application/octet-stream"
xhrObj.setRequestHeader("Content-Type","application/json");
// NOTE: Replace the "Ocp-Apim-Subscription-Key" value with a valid subscription key.
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","my key");
},
//don't forget this!
processData: false,
type: "POST",
// Request body
data: new Blob([fileContentArrayBuffer], { type: fileType })
}).done(function(data) {
alert(data);
// Get face rectangle dimensions
var faceRectangle = data[0].faceRectangle;
var faceRectangleList = $('#faceRectangle');
// Append to DOM
for (var prop in faceRectangle) {
faceRectangleList.append("<li> " + prop + ": " + faceRectangle[prop] + "</li>");
}
// Get emotion confidence scores
var scores = data[0].scores;
var scoresList = $('#scores');
// Append to DOM
for(var prop in scores) {
scoresList.append("<li> " + prop + ": " + scores[prop] + "</li>")
}
}).fail(function(err) {
alert("Error: " + JSON.stringify(err));
});
}
};
};
Assuming you have your key, the request URL for Emotion API should be
https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize?
You may also want to take a look at this website. It got similar code.
Sorry I can't use comment function as I am new here and don't have enough reputation to do so.
Could you double check with your api region? Because this error occurs when there is no resource found for given api key in a region.
And for accessing emotions you will need to pass parameters to api which will give you attributes for faces in response which contains emotions.

Function that returns download URL from Firebase storage

I'm writing this function to use in my angular app to evaluate ng-src in an ng-repeat list. I need to make the calls synchronous so that the value is correct each time the function is called. The problem is:
Why does this code return a value:
var storage = firebase.storage();
var returnVal; //causes sync issues
var getImageUrl = function (time) {
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
returnVal = url;
});
return returnVal;
};
But this doesn't work:
var storage = firebase.storage();
var getImageUrl = function (time) {
var returnVal; //so that this is specific to the function
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
returnVal = url; //I simply want to return the value of 'url'
});
return returnVal;
};
Any ideas how I can make the getImageUrl() function return the url from the .then?
This is the documentation link: https://firebase.google.com/docs/storage/web/download-files
Eventually I'll turn this into a $scope function to use similar to this:
<div ng-repeat="message in messages">
<img ng-src="{{ getImageUrl(message.time) }}">
</div>
Neither variation of your function will ever return a value that isn't null or undefined. You are performing an asynchronous call that will not wait for the result before continuing to execute the code below it. For example:
var storage = firebase.storage();
// Execute (1)
var getImageUrl = function (time) {
// Execute (2)
var returnVal;
// Execute (3)
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
// Execute (unknown)
returnVal = url;
});
// Execute (4)
return returnVal;
};
// Execute (unknown times)
You have no idea when the async call will return the data, but it will always be after return returnVal; therefore returnVal is null.
I recommend this:
$scope.images = [];
$scope.messages = { // whatever };
for (m in $scope.messages) {
storage.ref('images/' + time + '.jpg').getDownloadURL().then(function (url) {
// Might need $scope.$apply(function() {} ) surrounding
$scope.images.push(url);
});
}
Then in your view:
<div ng-repeat="image in images">
<img ng-src="{{ image }}">
</div>
The time for all this to load is dependent on the size of $scope.messages. If there are a large amount I would recommend changing your data structure so you do not have to make multiple calls to the database.
theblindprophet's answer contains a great explanation of why your current code doesn't work and a working solution.
As an alternative, you can simply return the so-called promise that getDownloadURL() returns. I haven't tested, but expect Angular to pick the promise up automatically.
var storage = firebase.storage();
var getImageUrl = function (time) {
return storage.ref('images/' + time + '.jpg').getDownloadURL();
};
And in your HTML you just keep:
<div ng-repeat="message in messages">
<img ng-src="{{ getImageUrl(message.time) }}">
</div>
You can use ajax for downlead file in firebase-storage
const link = linkYourFirebaseImage + folderStoreImage + '2F' + fileName;
// example: const link = https://firebasestorage.googleapis.com/v0/b/myApp.appspot.com/o/myDir%2F1608378322792.PNG;
function downloadImage(fileName, defaultImage) {
if (fileName.length == 0) return defaultImage;
let imageUrl;
$.ajax({
type: "GET",
async: false,
url: link ,
success: function (response) {
imageUrl = `${link}alt=media&token=${response.downloadTokens}`;
},
});
return imageUrl;
}
How to use ?
const myImage = downloadImage('myPath.png', '../default.png');

AngularJS undefined function

I have two angularJS $scope functions inside a main one. When calling the play() function there is an error stating that getPhoneGapPath() is undefined. What is the solution to this
My Code:
function DontAsk($scope){
$scope.getPhoneGapPath = function(){
var path = window.location.pathname;
path = path.substr( 0, path.length - 10 );
return 'file://' + path;
}
$scope.play= function(){
var os = navigator.platform;
if (os=='iPhone'){
var url = "sounds/DontEventAsk.mp3";
}
else{
var url = getPhoneGapPath() + "sounds/DontEventAsk.mp3";
}
var my_media = new Media(url,
// success callback
function() {
console.log("playAudio():Audio Success");
},
// error callback
function(err) {
console.log("playAudio():Audio Error: "+JSON.stringify(err));
});
// Play audio
my_media.play();
}}
Ideally I would want the getPhoneGapPath() to be defined and also outside the main function because I have multiple functions like the DontAsk() one.
Thanks a lot.
var url = $scope.getPhoneGapPath() + "sounds/DontEventAsk.mp3";
There is no getPhoneGapPath function in the scope. You are defining this function as a property of the $scope object, so you should use it accordingly:
$scope.getPhoneGapPath()

JavaScript OOP - Not able to set the public value from Ajax call inside a Class structure

i faced issue while writing a class specially for handling Ajax calls & its response.
Purpose of below code : Based on user records exist in database, i need to set the flag "isPersonalDivRequiredFlag" for further use.
// New ajax request class
function ajaxRequestHandler(){
this.needOutPutInJSON = 0;
this.url = "/libraries/ajaxHelper.php";
this.requestType = "POST";
this.isPersonalDivRequiredFlag = 0;
};
// Methods written for Class ajaxRequestHandler
ajaxRequestHandler.prototype = {
sentRequest : function(userData, typeID){
var options = {type: this.requestType, context: this, url: this.url, data: { data: userData, type: typeID }};
if(this.needOutPutInJSON){
options.dataType = "json";
}
// Check whether user want to see the response
options.success = function(rec){
if(rec == "1"){
this.isPersonalDivRequiredFlag = 1;
}
};
//Jquery Ajax
$.ajax(options);
},
enableJSONoutput : function(){
this.needOutPutInJSON = 1;
},
getFlagValue : function(){
return this.isPersonalDivRequiredFlag;
},
setFlagValue : function(){
console.log('Setflag Func called.');
this.isPersonalDivRequiredFlag = 1;
}
};
And i use the code as below.
var newRequest = new ajaxRequestHandler();
console.log('Before change [Value of isPersonalDivRequiredFlag variable] : ' + newRequest.getFlagValue()); // Output 0
newRequest.sentRequest({}, "recordExist");
console.log('After change [Value of isPersonalDivRequiredFlag variable] : ' + newRequest.getFlagValue()); // Output 0
And when i set the flag "isPersonalDivRequiredFlag " to 1 inside the Success method of Ajax call but its unable to retain this value when it will be accessed through its own method "getFlagValue" function.
The whole piece of code will work fine if i remove Ajax call function & made it a normal prototype method. So i know the cause but not able to find any solution :(
what the things i tried already?
I found some techniques people suggested while Google it over internet.
a) Used this configuration inside Ajax call but no luck :(
context:this
b) inside Success method :
var myclass = this;
And called the prototype function as below
myclass.setFlagValue();
but no luck :(

how to determine when a request in completed in mootools?

I am new to moootools and I am creating a Template class,This is my code -
var Template = new Class({
Singleton : true,
template : '',
/* gets the component type template */
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
}
});
What I want to do is this :
var tpl = new Template();
tpl.get('component').setTemplateData({name:'yosy'});
The problem is when I am calling this code :
var tpl = new Template();
console.log( tpl.get('component') );
I am not getting my current Template object,I am getting is 'undefined'.
How I can make this chainable?
You are making an asynchronous call inside the get function. The request may take 100ms, 1s or 10s and by the time the get function finishes and returns, the request will still be pending. Instead what you need to do is, pass a callback function to get and call that on success.
get: function(componentType, successCallback) {
var request = new Request({
..,
onSuccess: successCallback
}).send();
}
Note that you are not returning anything from the get function. One example way to invoke this would be:
tpl.get('component', function(responseText) { alert(responseText); });
Your get function is missing a return value. If you want functions to chain you should return the object itself:
get : function(componentType){
var tplUrl = Core.getUrl('backend') + 'response/' + componentType + '/get_template.php',
that = this,
request = new Request({url: tplUrl, method : 'get',onSuccess : function(responseText){
that.template = responseText;
return that;
}}).send();
return this;
}

Categories