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()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 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 visible
For the second for loop use:
for (var p = this.numPages-1; p >= event.target.page; p--) {
Copy link to clipboard
Copied
Can you briefly share what are the suggestions that other community memebers have offered?
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.
Copy link to clipboard
Copied
Where does you use the script?
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).
Copy link to clipboard
Copied
For the second for loop use:
for (var p = this.numPages-1; p >= event.target.page; p--) {
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?
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
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!
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!
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.
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.......
Copy link to clipboard
Copied
The code doesn't change the content of the arrays.
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.
Copy link to clipboard
Copied
You don't need the arrays. For this you must modify the code.
Copy link to clipboard
Copied
How could I modify this so it runs faster?
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;
}
}
}
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.
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.