Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! 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
}
}
}
