Problem in my For Loop?

Participant ,
Jan 22, 2020

Copy link to clipboard

Copied

This has been infuriating me for a few hours, and it seems like the kind of problem fresh eyes can help with. The issue is explaining it all... I've mentioned my project numerous times, and the same 3 or 4 community members continue to rally to my cause, so I'll get right to it.

 

The following script is intended to run from a button which is next to a photo. It should move said photo and all photos past it down a slot, leaving the slot it was in "blank", ready for a different photo.

function insTop(){
//If the last photo is already filled in, this spawns a new page first
if(getFieldOn("botPh", this.numPages - 1).buttonGetIcon() != this.getField("blnk").buttonGetIcon()) spawnNewPage();

event.target.setFocus();
	
//these variables are arrays for the affected photos/captions
//they are filled in the order they appear in the document
var topPhs = [];
var topCaps = [];
var botPhs = [];
var botCaps = [];
for(var p = event.target.page; p < this.numPages; p++){//loops through each page starting where the button is clicked
    topPhs.push(getFieldOn("topPh", p));
    topCaps.push(getFieldOn("topCap", p));
    botPhs.push(getFieldOn("botPh", p));
    botCaps.push(getFieldOn("botCap", p));
}//end of pages for loop; arrays are now filled in page order

for(var p = event.target.page; p < this.numPages; p++){//loops back through each page replacing fields
    var tP = getFieldOn("topPh", p);
    var tC = getFieldOn("topCap", p);
    var bP = getFieldOn("botPh", p);
    var bC = getFieldOn("botCap", p);

    bP.buttonSetIcon(topPhs[p - event.target.page].buttonGetIcon());
    bC.value = topCaps[p - event.target.page].value;

    if(p == event.target.page){
        tP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
        tC.value = "";
    }else{
        tP.buttonSetIcon(botPhs[p - event.target.page - 1].buttonGetIcon());
        tC.value = botCaps[p - event.target.page - 1].value;
    }

}//end of pages for loop
    
}

The issue is definitely somehwere near the end, possibly in the if statement. It is supposed to bump each picture either from the top of its page to the bottom of its page, or from the bottom of its page to the top of the next page. 

 

before running insTop()before running insTop()This shows the before state. We are on pg 5 of the PDF, and the photos are labeled to easily see the order.after running insTop()after running insTop()After running the above script, I now have blank, 1; 1, 3; 3, 5 (expected: blank, 1; 2, 3; 4, 5). The bottom photo is working fine. But the top... The most baffling part is the photos its assigning to the top should not be stored in botPhs[] at all! I've pulled all the small parts of this out, and I cannot for the life of me understand what I've done. Please help!field names visiblefield names visible

Adobe Community Professional
Correct answer by Bernd Alheit | Adobe Community Professional

For the second for loop use:

for (var p = this.numPages-1; p >= event.target.page; p--) {

TOPICS
Acrobat SDK and JavaScript, Create PDFs, General troubleshooting, PDF forms

Views

87

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Problem in my For Loop?

Participant ,
Jan 22, 2020

Copy link to clipboard

Copied

This has been infuriating me for a few hours, and it seems like the kind of problem fresh eyes can help with. The issue is explaining it all... I've mentioned my project numerous times, and the same 3 or 4 community members continue to rally to my cause, so I'll get right to it.

 

The following script is intended to run from a button which is next to a photo. It should move said photo and all photos past it down a slot, leaving the slot it was in "blank", ready for a different photo.

function insTop(){
//If the last photo is already filled in, this spawns a new page first
if(getFieldOn("botPh", this.numPages - 1).buttonGetIcon() != this.getField("blnk").buttonGetIcon()) spawnNewPage();

event.target.setFocus();
	
//these variables are arrays for the affected photos/captions
//they are filled in the order they appear in the document
var topPhs = [];
var topCaps = [];
var botPhs = [];
var botCaps = [];
for(var p = event.target.page; p < this.numPages; p++){//loops through each page starting where the button is clicked
    topPhs.push(getFieldOn("topPh", p));
    topCaps.push(getFieldOn("topCap", p));
    botPhs.push(getFieldOn("botPh", p));
    botCaps.push(getFieldOn("botCap", p));
}//end of pages for loop; arrays are now filled in page order

for(var p = event.target.page; p < this.numPages; p++){//loops back through each page replacing fields
    var tP = getFieldOn("topPh", p);
    var tC = getFieldOn("topCap", p);
    var bP = getFieldOn("botPh", p);
    var bC = getFieldOn("botCap", p);

    bP.buttonSetIcon(topPhs[p - event.target.page].buttonGetIcon());
    bC.value = topCaps[p - event.target.page].value;

    if(p == event.target.page){
        tP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
        tC.value = "";
    }else{
        tP.buttonSetIcon(botPhs[p - event.target.page - 1].buttonGetIcon());
        tC.value = botCaps[p - event.target.page - 1].value;
    }

}//end of pages for loop
    
}

The issue is definitely somehwere near the end, possibly in the if statement. It is supposed to bump each picture either from the top of its page to the bottom of its page, or from the bottom of its page to the top of the next page. 

 

before running insTop()before running insTop()This shows the before state. We are on pg 5 of the PDF, and the photos are labeled to easily see the order.after running insTop()after running insTop()After running the above script, I now have blank, 1; 1, 3; 3, 5 (expected: blank, 1; 2, 3; 4, 5). The bottom photo is working fine. But the top... The most baffling part is the photos its assigning to the top should not be stored in botPhs[] at all! I've pulled all the small parts of this out, and I cannot for the life of me understand what I've done. Please help!field names visiblefield names visible

Adobe Community Professional
Correct answer by Bernd Alheit | Adobe Community Professional

For the second for loop use:

for (var p = this.numPages-1; p >= event.target.page; p--) {

TOPICS
Acrobat SDK and JavaScript, Create PDFs, General troubleshooting, PDF forms

Views

88

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Jan 22, 2020 0
Adobe Community Professional ,
Jan 22, 2020

Copy link to clipboard

Copied

Can you briefly share what are the suggestions that other community memebers have offered?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 22, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

Sorry, I didn't mean regarding this specific question. I have been asking questions about this specific project for a couple weeks so far, but I have not posted regarding this situation.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Adobe Community Professional ,
Jan 22, 2020

Copy link to clipboard

Copied

Where does you use the script?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 22, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

I immediately regretted not attaching the PDF when I posted. Hopefully my link works right.

 

The script I originally posted is stored at document level and is assigned to run on mouse up of the 'Insert' button (temporarily only found on page 3 of the document).

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Adobe Community Professional ,
Jan 23, 2020

Copy link to clipboard

Copied

For the second for loop use:

for (var p = this.numPages-1; p >= event.target.page; p--) {

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

AHH IT WORKED!!! But why?? I get that this loops it back through the pages backwards, but why on earth does that matter?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Adobe Community Professional ,
Jan 23, 2020

Copy link to clipboard

Copied

After changing the first page, the second page get the wrong information from the first page.

 

first page: 1, 2
second page: 3, 4

 

after insert:

 

first page: blank, 1
second page: 1, 3

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

But doesn't it fill my arrays with the state the doc is in with the first for loop before it changes anything with the second for loop? The first for loop should finish with all the arrays properly filled in, then the next loop should be looking at their values, and not changing them... I would have thought. That was at least what I meant for it to do. The arguemnts for setButtonIcon are array values, not the bP object variable that gets changed as the second loop runs. Why is the content or the arrays changing as the second loop runs? Again, I greatly appreciate the help/fix!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

I substituted in the following:

		if(p == event.target.page){
			tP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
			tC.value = "";
		}
		if(p == 3){
			tP.buttonSetIcon(botPhs[0].buttonGetIcon());
			tC.value = botCaps[0].value;
		}else if(p == 4){
			tP.buttonSetIcon(botPhs[1].buttonGetIcon());
			tC.value = botCaps[1].value;
		}

and got the exact same result as the first version (where the array index is calculated). I think this confirms something is going wrong with my array botPhs[]. The photos its applying to the top buttons should not be stored in botPhs at all (at least at the time the arrays are populated). They are only on top photos when the array is made. I know this has to be some misunderstanding on my part! Maybe someone could translate my original posted script to pseudo code. When I try to do that, it seems to me that it should work. So frustrating!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Adobe Community Professional ,
Jan 23, 2020

Copy link to clipboard

Copied

You have changed the bottom of the first page before you transfer this to the top of the second page.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Participant ,
Jan 23, 2020

Copy link to clipboard

Copied

Something simliar happened when I made the button that does this same thing for the bottom photo. I don't understand it though.

function insBot(){

    //If the last photo is already filled in, this spawns a new page first
    if(getFieldOn("botPh", this.numPages - 1).buttonGetIcon() != this.getField("blnk").buttonGetIcon()) spawnNewPage();

    event.target.setFocus();
	
	//these variables are arrays for the affected photos/captions
	//they are filled in the order they appear in the document
	var topPhs = [];
	var topCaps = [];
	var botPhs = [];
	var botCaps = [];
	for(var p = event.target.page; p < this.numPages; p++){//loops through each page starting where the button is clicked
		topPhs.push(getFieldOn("topPh", p));
		topCaps.push(getFieldOn("topCap", p));
		botPhs.push(getFieldOn("botPh", p));
		botCaps.push(getFieldOn("botCap", p));
	}//end of pages for loop; arrays are now filled in page order

	for(var p = this.numPages-1; p >= event.target.page; p--) {//loops back through each page replacing fields
		var tP = getFieldOn("topPh", p);
		var tC = getFieldOn("topCap", p);
		var bP = getFieldOn("botPh", p);
		var bC = getFieldOn("botCap", p);

		if(p == event.target.page){
			bP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
			bC.value = "";
		}else{
			bP.buttonSetIcon(topPhs[p - event.target.page].buttonGetIcon());
			bC.value = topCaps[p - event.target.page].value;
			tP.buttonSetIcon(botPhs[p - event.target.page - 1].buttonGetIcon());
			tC.value = botCaps[p - event.target.page - 1].value;			
		}

	}//end of pages for loop
    
}

 It messed up similar to what the other button was doing when the end looked like this instead

if(p == event.target.page){
	bP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
	bC.value = "";
}else{
	tP.buttonSetIcon(botPhs[p - event.target.page - 1].buttonGetIcon());
	tC.value = botCaps[p - event.target.page - 1].value;
	bP.buttonSetIcon(topPhs[p - event.target.page].buttonGetIcon());
	bC.value = topCaps[p - event.target.page].value;
}

I cannot understand why this works differently. The getButtonIcon() is paired with the array. Is the value of tP, bP etc. affecting the values in the topPhs[] and botPhs[] arrays?? Does the content of the array change dynamically since the contents are objects? That must be it.......

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 23, 2020 0
Adobe Community Professional ,
Jan 24, 2020

Copy link to clipboard

Copied

The code doesn't change the content of the arrays.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0
Participant ,
Jan 24, 2020

Copy link to clipboard

Copied

That makes sense. So since the array holds field objects and not just properties of the fields, the data is dynamic right? It doesn't store that "state" of the object at the time statically, it points to the object itself? So for example, I put a field, "textBx", in an array, fields[0], and the value is something, say "Hello". Then later: textBx.value = "Hello World", now fields[0].value = "Hello World", right? Is there a way to statically store field properties? I suppose making a second field, hidden somewhere.

 

Will storing just the icons of the photos and the value of the text fields make this code run noticeably faster? It does lag a little when its all local, and in service it will be much slower as it gets used on a server with photos from elsewhere on the server.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0
Adobe Community Professional ,
Jan 24, 2020

Copy link to clipboard

Copied

You don't need the arrays. For this you must modify the code.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0
Participant ,
Jan 24, 2020

Copy link to clipboard

Copied

How could I modify this so it runs faster?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0
Adobe Community Professional ,
Jan 24, 2020

Copy link to clipboard

Copied

Something like this:

function insTop(){
//If the last photo is already filled in, this spawns a new page first
if(getFieldOn("botPh", this.numPages - 1).buttonGetIcon() != this.getField("blnk").buttonGetIcon()) spawnNewPage();

event.target.setFocus();

for (var p = this.numPages-1; p >= event.target.page; p--) {
    var tP = getFieldOn("topPh", p);
    var tC = getFieldOn("topCap", p);
    var bP = getFieldOn("botPh", p);
    var bC = getFieldOn("botCap", p);

    bP.buttonSetIcon(tP.buttonGetIcon());
    bC.value = tC.value;

    if(p == event.target.page){
        tP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
        tC.value = "";
    }else{
        tP.buttonSetIcon(getFieldOn("botPh", p-1).buttonGetIcon());
        tC.value = getFieldOn("botCap", p-1).value;
    }
}
}

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 1
Participant ,
Jan 24, 2020

Copy link to clipboard

Copied

Awesome, Bernd! The code is a lot shorter. I think it exectues faster too, but it's a little hard to tell. I appreciate the help and suggestions.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0
Participant ,
Jan 24, 2020

Copy link to clipboard

Copied

So I tried following your lead on a simliar function. This one is used to delete a photo in the middle somehwere and bump each one below it up a slot. I started to have it iterate the pages from the bottom up like you did, but I realized this case is the opposite and I have to go top down. Here's what I ended up with:

 

for(var p = event.target.page; p < this.numPages; p++){
    var tP = getFieldOn("topPh", p);
    var tC = getFieldOn("topCap", p);
    var bP = getFieldOn("botPh", p);
    var bC = getFieldOn("botCap", p);
    if(p == event.target.page){//first page: remove the bottom photo only
        if(p == (this.numPages - 1)){//first page = last page: no replacement
            bP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
            bC.value = "";
        }else{
            bP.buttonSetIcon(getFieldOn("topPh", p + 1).buttonGetIcon());
            bC.value = getFieldOn("topCap", p + 1).value;
        }//end if
    }else if(p != (this.numPages - 1)){//middle pages: change top and bottom
        tP.buttonSetIcon(bP.buttonGetIcon());
        tC.value = bC.value;
        bP.buttonSetIcon(getFieldOn("topPh", p + 1).buttonGetIcon());
        bC.value = getFieldOn("topCap", p + 1).value;
    }else{//last page: set last photo to blank
        tP.buttonSetIcon(bP.buttonGetIcon());
        tC.value = bC.value;
        bP.buttonSetIcon(this.getField("blnk").buttonGetIcon());
        bC.value = "";
    }//end if
}//end of for loop

 

It works. Does it seem like there an extra step in my if logic though? In my mind, there are 3 cases to consider: first page (top photo doesn't change), last page (bottom will be blank), and everything in between (both probably change, unless blanks are in the middle somehwere). Do you see a way to make this more efficient?

 

Also: I have 4 separate scripts for inserting or deleting top or bottom. Because each one has 'event.target' in it, it's my understanding I need to have unique fields and not widgets of the same field. Is this necessarily true? Therefore I create the buttons in my newPage() script instead of having them on the template I'm using. My newPage() script is already the biggest one, mainly due to all the fields it creates.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Jan 24, 2020 0