Community Tip - Visit the PTCooler (the community lounge) to get to know your fellow community members and check out some of Dale's Friday Humor posts! X
Hello,
I would like to check if app/resources/IMAGES/Filename.JPG exists or not, and then display scrolling arrows (left and right) if multiple images exist. I can figure out the scrolling arrows, and how to change the 3D image widget, but I can't find a way to check if JPG files are uploaded. I display a different image for each step of an animation, but some steps will have multiple images associated with them.
I have tried Stack Overflow: Check synchronously if file/directory exists in Node.js
but I get the error in my console "TypeError: Cannot read property 'access' of undefined"
var name = // code I use to concatenate a filename string ending in .jpg var p = "app/resources/IMAGES/"+name; fs.access(p, error => { if (!error) { console.log("exists: "+p); } else { console.log("does not exist: "+p); }
Any suggestions?
Thanks
Solved! Go to Solution.
I finally got it working yesterday. Instead of creating a for loop, I make the function run itself again each time it receives a response. Of course, this could go on forever. So I built in a variable called "proceed" that is true or false. Once a limit has been reached (such as 10 photos per step) the loop stops. That's more or less how my code is working. It's a nice trick -- when you want to "pause" a function until something happens, just put the function call inside of the function in order to create a loop:
var proceed = true;// change back to false later var waitUntilFinished = false; var j = 1;//step var k = 1;//image var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]] var Xm = []; // metadata for X // Change Image per step $scope.app.stepImage = function (Achapter=1,Astep=1,Aimg=1){ $scope.view.wdg['U-20-1']['src'] = 'app/resources/IMAGES/CH-'+Achapter+'_STEP-'+Astep+'_IMG-'+Aimg+'.jpg'; // below is code for finding out if multiple images exist per a step, and if so, showing arrows if(Xm[Achapter-1]===undefined){ waitUntilFinished = true;console.log("**a** X=");console.log(X); proceed = true; $scope.app.getX(Achapter,Astep,Aimg); } if(!waitUntilFinished){ // control visibility of <[]> and image resource dispImgArrows(Achapter,Astep,Aimg);console.log("**c**") } } // Show arrows if multiple images exist per a single step $scope.app.getX = function(i=1,j=1,k=1){ var j1=j;var k1=k;//capture original inputs if(j>chapters[i-1][4]){console.log("**d**");Xm[i-1]=true;proceed=false;i=1;j=1;k=1;waitUntilFinished=false;$scope.app.stepImage(i,j1,k1)} if(X[0]===undefined){ for(ch=0;ch<chapters.length;ch++){ X.push([]);Xm.push(undefined); for(st=0;st<chapters[ch][4];st++){ X[ch].push(0);}}} if(proceed){ var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG"; var p = "app/resources/IMAGES/"+name; console.log(p); $http.get(p).then(successCallback, errorCallback); function successCallback(response){ console.log("i="+i+"\nj="+j+"\nk="+k+"\nX="); console.log(X); k++; X[i-1][j-1]++; $scope.app.getX(i,j,k); } function errorCallback(error){ k=1;// reset j++;// step # console.log("chapters ="); console.log(chapters) console.log("i="+i+"\nj="+j+"\nk="+k+"\nX="); console.log(X); $scope.app.getX(i,j,k); } } }
So essentially when you go to a chapter you automatically trigger a function to (1) create an array with sub-arrays for each chapter. (2) populate the sub array for that particular chapter with a list of numbers representing the number of images for each step (3) populate a "meta-data" array Xm that tells you which chapters have been visited and thus the number of images per step has been recorded for them. So for instance, after visiting chapter 2 the variables look something like this X = [[0,0,0,0],[0,0,0,0,0,0,0],[1,1,1,2,1,3,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0]] and Xm = [undefined, undefined, true, undefined, undefined]
If you want the simplified version of this (the core functionality for a recursive check) then use this code:
var proceed = true;// change back to false later var j = 1; //step var k = 1; //image var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]] var Xm = []; // by the way "chapters" is an array with chapter metadata, and chapters[i][4] tells you the number of steps for chapter # i // Show arrows if multiple images exist per a single step $scope.app.getX = function(i=1,j=1,k=1){ // this just creates an array X with placeholders [[0,0,0],[0,0],[0,0,0,0]] and Xm if(j>chapters[i-1][4]){;Xm[i-1]=true;proceed=false;i=1;j=1;k=1} if(X[0]===undefined){ for(ch=0;ch<chapters.length;ch++){ X.push([]);Xm.push(undefined); for(st=0;st<chapters[ch][4];st++){ X[ch].push(0);}}} if(proceed){ var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG"; var p = "app/resources/IMAGES/"+name; $http.get(p).then(successCallback, errorCallback); function successCallback(response){ k++; X[i-1][j-1]++; $scope.app.getX(i,j,k); \\ use this instead of a for loop } function errorCallback(error){ k=1;// reset j++;// step # $scope.app.getX(i,j,k); \\ use this instead of a for loop } } }
Try this Function;
function doesFileExist(urlToFile)
{
var xhr = new XMLHttpRequest();
xhr.open('HEAD', urlToFile, false);
xhr.send();
if(xhr.status !="200") {
console.log("File not exist");
}
else {
console.log("File Exist")
}
}
doesFileExist('app/resources/Uploaded/FILENAME.ext');
I hope to be proved helpful
Giuseppe.
additional to suggested option by @Giuseppe_Fiore
you can use also the $http service e.g. to check if a file (var below jsonFile) is in particular Studio folder:
$http.get('app/resources/Uploaded/' + jsonFile).success(function(data, status, headers, config) { console.log("Found :"+jsonFile+" in folder app/resources/Uploaded/"); }) .error(function(data, status, headers, config) { console.log("Could NOT find :"+jsonFile+" in folder app/resources/Uploaded/"); })
OK , I see that here is the key word is in sonorously what I overlooked – so far I think the both suggested methods , which works fine are asynchronous calls
What is exact the problem so that is necessarily to use synchronous call ?
Maybe you can use some constucts with the promises as mention in the stack overflow post
Thank you both,
@RolandRaytchev , I searched for $http.get(...).sucess and found that it has been replaced in later versions of angular: See StackOverflow:
The .success
syntax was correct up to Angular v1.4.3.
For versions up to Angular v.1.6, you have to use then
method.
I was able to successfully use
$scope.app.testA = function(){ var testA = "app/resources/IMAGES/CH-5_STEP-14_IMG-1.jpg"; $http.get(testA).then(successCallback, errorCallback); function successCallback(response){ console.log(testA+' exists');//success code } function errorCallback(error){ console.log(testA+' does not exist');//error code } }
However when I use loops, I run into trouble:
This is my code:
// Show arrows if multiple images exist per a single step var imagesPerStep = []; ///// format: [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]] $scope.app.multipleImages = function(){ // When first called, find out which steps have multiple images for(i=0;i<chapters.length-1;i++){ // loop through chapters imagesPerStep.splice(i,1,[]);// add a sub-array[] for chapter(i) for(j=0;j<chapters[i][4];j++){ // loop through steps [4]= #of steps imagesPerStep[i].push(0);// create new element (step) within a sub-array (chapter) for(k=0;k<10;k++){// loop through images per step var name = "CH-"+(i+1).toString()+"_STEP-"+(j+1).toString()+"_IMG-"+(k+1).toString()+".JPG"; //console.log("name = "+name); var p = "app/resources/IMAGES/"+name; $http.get(p).then(successCallback, errorCallback); function successCallback(response){ //success code imagesPerStep[i][j]++;//if the file exists, add one } function errorCallback(error){ //error code } } } } }
I think that the problem might be the loop. Before the response ever returns, the loop has already finished and [i] and [j] are no longer the same values. I need to somehow pause the loop until a response is returned.
Any ideas on how to pause?
Thanks!
Hi @Wes_Tomer ,
I took a look on your code and I think it could not work.
The problem is when you have the call :
imagesPerStep[i][j]++
so, when the call is done you do not know what is the value if i and j...
I do not think that you need to synchronize it in fact but you need to:
1.) past i an j as arguments to the call of the $http.get() -> example:
... var p = "app/resources/IMAGES/"+name; var dataIN=[i,j]; $http.get(p,dataIN).then(successCallback, errorCallback); function successCallback(response){ //success code imagesPerStep[ dataIN[0] ][ dataIN[1] ]++;//if the file exists, add one } ....
2.) if there is still problem , you can try first to initialize the whole array imagesPerStep[][] over the whole range with 0 and then set to 1 only for the existing objects in the loop .
I finally got it working yesterday. Instead of creating a for loop, I make the function run itself again each time it receives a response. Of course, this could go on forever. So I built in a variable called "proceed" that is true or false. Once a limit has been reached (such as 10 photos per step) the loop stops. That's more or less how my code is working. It's a nice trick -- when you want to "pause" a function until something happens, just put the function call inside of the function in order to create a loop:
var proceed = true;// change back to false later var waitUntilFinished = false; var j = 1;//step var k = 1;//image var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]] var Xm = []; // metadata for X // Change Image per step $scope.app.stepImage = function (Achapter=1,Astep=1,Aimg=1){ $scope.view.wdg['U-20-1']['src'] = 'app/resources/IMAGES/CH-'+Achapter+'_STEP-'+Astep+'_IMG-'+Aimg+'.jpg'; // below is code for finding out if multiple images exist per a step, and if so, showing arrows if(Xm[Achapter-1]===undefined){ waitUntilFinished = true;console.log("**a** X=");console.log(X); proceed = true; $scope.app.getX(Achapter,Astep,Aimg); } if(!waitUntilFinished){ // control visibility of <[]> and image resource dispImgArrows(Achapter,Astep,Aimg);console.log("**c**") } } // Show arrows if multiple images exist per a single step $scope.app.getX = function(i=1,j=1,k=1){ var j1=j;var k1=k;//capture original inputs if(j>chapters[i-1][4]){console.log("**d**");Xm[i-1]=true;proceed=false;i=1;j=1;k=1;waitUntilFinished=false;$scope.app.stepImage(i,j1,k1)} if(X[0]===undefined){ for(ch=0;ch<chapters.length;ch++){ X.push([]);Xm.push(undefined); for(st=0;st<chapters[ch][4];st++){ X[ch].push(0);}}} if(proceed){ var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG"; var p = "app/resources/IMAGES/"+name; console.log(p); $http.get(p).then(successCallback, errorCallback); function successCallback(response){ console.log("i="+i+"\nj="+j+"\nk="+k+"\nX="); console.log(X); k++; X[i-1][j-1]++; $scope.app.getX(i,j,k); } function errorCallback(error){ k=1;// reset j++;// step # console.log("chapters ="); console.log(chapters) console.log("i="+i+"\nj="+j+"\nk="+k+"\nX="); console.log(X); $scope.app.getX(i,j,k); } } }
So essentially when you go to a chapter you automatically trigger a function to (1) create an array with sub-arrays for each chapter. (2) populate the sub array for that particular chapter with a list of numbers representing the number of images for each step (3) populate a "meta-data" array Xm that tells you which chapters have been visited and thus the number of images per step has been recorded for them. So for instance, after visiting chapter 2 the variables look something like this X = [[0,0,0,0],[0,0,0,0,0,0,0],[1,1,1,2,1,3,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0]] and Xm = [undefined, undefined, true, undefined, undefined]
If you want the simplified version of this (the core functionality for a recursive check) then use this code:
var proceed = true;// change back to false later var j = 1; //step var k = 1; //image var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]] var Xm = []; // by the way "chapters" is an array with chapter metadata, and chapters[i][4] tells you the number of steps for chapter # i // Show arrows if multiple images exist per a single step $scope.app.getX = function(i=1,j=1,k=1){ // this just creates an array X with placeholders [[0,0,0],[0,0],[0,0,0,0]] and Xm if(j>chapters[i-1][4]){;Xm[i-1]=true;proceed=false;i=1;j=1;k=1} if(X[0]===undefined){ for(ch=0;ch<chapters.length;ch++){ X.push([]);Xm.push(undefined); for(st=0;st<chapters[ch][4];st++){ X[ch].push(0);}}} if(proceed){ var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG"; var p = "app/resources/IMAGES/"+name; $http.get(p).then(successCallback, errorCallback); function successCallback(response){ k++; X[i-1][j-1]++; $scope.app.getX(i,j,k); \\ use this instead of a for loop } function errorCallback(error){ k=1;// reset j++;// step # $scope.app.getX(i,j,k); \\ use this instead of a for loop } } }
By the way, if all this code looks confusing, here is the "skeleton" that I built on top of. Hopefully this helps to simplify things a little.
$scope.app.getX = function(){ var myString = "app/resources/IMAGES/filename.jpg"; $http.get(myString).then(successCallback, errorCallback); function successCallback(response){ // code you want to execute when image IS found } function errorCallback(error){ // code you want to execute when image is NOT found } } }