Copy link to clipboard
Copied
In the following simplified code I get the error that "the last command could not be undone".
Anyone knows WHY I get this error?
QGlobalSemaphores = [];
// ECMAScript 3 has no classes
function WaitForIt(callback, object) {
this.object = object;
this.answer = null;
this.index = -1;
this.callback = callback;
}
function doSubscript(index) {
mySemaphore = QGlobalSemaphores[index];
mySemaphore.callback(mySemaphore.object);
alert("executed");
}
function executeSubscript(callback, object) {
var w = new WaitForIt(callback, object);
w.index = QGlobalSemaphores.push(w) - 1;
app.doScript(doSubscript,ScriptLanguage.JAVASCRIPT,[w.index],UndoModes.FAST_ENTIRE_SCRIPT,'FE-Test');
}
function deleteLayers(obj) {
var doc = app.activeDocument;
var i = doc.layers.length;
while (i-->1) {
doc.layers[i].remove();
}
}
function test() {
executeSubscript(deleteLayers, null);
app.undo(); // <-- I get the error here.
}
app.doScript(test,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'Callback-Test');
I didnt get a solution, I got some workarounds.
By @Lordrhavin
well. workarounds are solutions for situations where there are no other solutions.
Copy link to clipboard
Copied
I suspect it is the nested doScripts. Try the undo after the app.doScript(test....
P.
Copy link to clipboard
Copied
Yeah, thats sadly not what i need -.-
I need to undo the subscript, not the entire script.
Copy link to clipboard
Copied
just a shot in the dark but will the default undo mode 'script request' make a difference?
Copy link to clipboard
Copied
You have probably tried this already but if not, try UndoModes.ENTIRE_SCRIPT rather than UndoModes.FAST_ENTIRE_SCRIPT because I recall that users have reported issues related to Undo with FAST_ENTIRE_SCRIPT. There is an old article that discusses.
I would be tempted to test the various UndoModes in your inner and outer doScripts. Does any combination of them give you the desired result with no error? Maybe it's just that using FAST_ENTIRE_SCRIPT *and then undo-ing it* is not going to work?
- Mark
Copy link to clipboard
Copied
I tested all 16 combinations.
- All combinations throw the error.
- If the outher script is set to SCRIPT_REQUEST, it does not undo automatically. Further, the inner script has *then* the following results:
ENTIRE_SCRIPT or FAST_ENTIRE_SCRIPT: I can manually undo everything in one step.
SCRIPT_REQUEST: I can manually undo everything stepwise.
The combination SCRIPT_REQUEST on mainscript and AUTO_UNDO on subscript didnt undo and I couldnt even undo manually; I had to reload the doc.
I also tested doing undo in a try-clause. It ommited the error but didnt undo at all 😄
Copy link to clipboard
Copied
Hi @Lordrhavin , Have you run your deleteLayers(obj) function by itself to check if it is doing what you expect?
A document has to have at least one layer, so the function would throw an error on a single layer document, and on a multi layer doc it only removes half the layers. Something like this, which loops an array rather than a collection, would remove all the layers (and their contents) except for the bottom layer:
deleteLayers("hi")
function deleteLayers(obj) {
var lyr = app.activeDocument.layers.everyItem().getElements();
for (var i = lyr.length-2; i > -1; i--) {
lyr[i].remove();
}
$.writeln(obj)//returns hi
}
Copy link to clipboard
Copied
Yes, I know that it i not deleting the last layer. But as it does this without any error and I also get this error if I just start with i=1, I dont saw the difference in posting that code.
Copy link to clipboard
Copied
I dont saw the difference in posting that code.
With your function I get this:
Before:
After
With the reverse array loop I get this
Copy link to clipboard
Copied
yes, this is oversimplified. Im tracking the error. You get the same error if you just kill one arbitrary layer. deleteLayer just had to do smething to my demo-doc, so i really didn't care if it does this correctly. I updated the code above.
Copy link to clipboard
Copied
yes, this is oversimplified. Im tracking the error. You get the same error if you just kill one arbitrary layer. deleteLayer just had to do smething to my demo-doc, so i really didn't care if it does this correctly. I updated the code above.
By @Lordrhavin
Do not delete i-th layer - becuase as @rob day pointed out - you'll be skipping elements - delete last or first one - depends on which one you wan to keep:
function deleteLayers(obj) {
var doc = app.activeDocument;
var i = doc.layers.length;
while (i-->1) {
doc.layers[-1].remove();
}
}
Copy link to clipboard
Copied
app.activeDocument.layers.length is n= "it has n layer(s)"
app.activeDocument.layers is base 0
var i = 10;
while (i-->1) {
// i goes 9 to 1
}
It actually deletes all layers except the zeroth.
Copy link to clipboard
Copied
I think you need app.activeDoucument.undo() rather than app.undo(). This works for me:
var doc = app.activeDocument;
function deleteLayers() {
doc.layers[0].remove();
}
app.doScript(deleteLayers,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'DeleteLayer');
alert("Restoring Layer")
//app.undo();//throws Unable to undo the last command. error
doc.undo()
Copy link to clipboard
Copied
I still get the same error. Did you call the subscript?
Copy link to clipboard
Copied
I’m not sure what’s going on with your code, my example just shows that app.undo() always throws an error with doScript()—it has to be app.activeDocument.undo().
I think you should watch out for the difference between collections and arrays—layers is a collection not an array of layers. A collection is similar to an array but they do not share the same methods. @Robert at ID-Tasker while loop could also be written like this where I’m explicity using the collection’s firstItem() and lastItem() methods to remove all the items above or below.
var doc = app.activeDocument;
function deleteLayers() {
var i = app.activeDocument.layers.count();
while (i-->1) {
//doc.layers.firstItem().remove();//removes all layers except for the bottom layer
doc.layers.lastItem().remove();//removes all layers except for the top layer
}
}
app.doScript(deleteLayers,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'DeleteLayer');
alert("Restoring Layers")
//app.undo();//throws Unable to undo the last command. error
doc.undo()
Copy link to clipboard
Copied
Yeah, but that is not the point. I cant see a subscript in you code. Try this even more simplified version:
function inner() {
var doc = app.activeDocument;
var i = doc.layers.length;
while (i-->1) {
doc.layers.lastItem().remove();
}
}
function outher() {
app.doScript(inner,ScriptLanguage.JAVASCRIPT,[],UndoModes.SCRIPT_REQUEST,'inner');
alert("pause");
app.activeDocument.undo(); //<- error
}
app.doScript(outher,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'outher');
Copy link to clipboard
Copied
I don‘t think it‘s going to work—the pause and undo have to happen after outher is called.
function inner() {
var doc = app.activeDocument;
var i = doc.layers.length;
while (i-->1) {
doc.layers.lastItem().remove();
}
}
function outher() {
app.doScript(inner,ScriptLanguage.JAVASCRIPT,[],UndoModes.SCRIPT_REQUEST,'outher');
}
app.doScript(outher,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'inner');
alert("pause");
app.activeDocument.undo();
Copy link to clipboard
Copied
Is there a problem with running the doScripts sequentially?
function inner() {
var doc = app.activeDocument;
var i = doc.layers.length;
while (i-->1) {
doc.layers.lastItem().remove();
}
}
app.doScript(inner,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'inner');
alert("Oops Restoring layers");
app.activeDocument.undo();
alert("Deleting them again");
app.doScript(inner,ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT,'inner');
alert("Wait Just Kidding");
app.activeDocument.undo();
Copy link to clipboard
Copied
>Is there a problem with running the doScripts sequentially?
Yes. The doScript encapsulate the blocks I need to undo. Still, after executing th script, Strg+Z should undo everything.
Copy link to clipboard
Copied
>Is there a problem with running the doScripts sequentially?
Yes. The doScript encapsulate the block I need to undo.
By @Lordrhavin
Why do you need to undo the block?
Copy link to clipboard
Copied
- Userdialog asks which layers to export at which setting into which file.
- Skript iterates tru settings, calls subscript for each setting
subskript does
- delete layers not to export
- set layer-state on those to export (normal, hidden, unprintable, hidden+unprintabe)
- export to file(s)
Now skript undoes and start again for next setting.
Copy link to clipboard
Copied
- Userdialog asks which layers to export at which setting into which file.
By @Lordrhavin
- Skript iterates tru settings, calls subscript for each setting
subskript does
- delete layers not to export
- set layer-state on those to export (normal, hidden, unprintable, hidden+unprintabe)
- export to file(s)
Now skript undoes and start again for next setting.
Well... next time please describe your workflow / what you want to achieve - you'll get the solution quicker...
Instead of finghting with UNDO - make a copy of the file, do what you want to do on the copy - delete the copy.
Do the above for each step / iteration.
Copy link to clipboard
Copied
Thee > next time please describe your workflow / what you want to achieve - you'll get the solution quicker
I didnt get a solution, I got some workarounds.
Me > Anyone knows WHY I get this error?
That is still not answered. I filed a bug report, as I think this a false-negative error .
https://indesign.uservoice.com/forums/601180-adobe-indesign-bugs/suggestions/48231980-undo-does-work...
Copy link to clipboard
Copied
Thee > next time please describe your workflow / what you want to achieve - you'll get the solution quicker
I didnt get a solution, I got some workarounds.
By @Lordrhavin
I'm sorry, what I meant, there is no need for you to try undoing things - what you want to achieve would be much easier if you make a copy of your original file, do show/hide/delete of the layers, export - and then start over with a new copy of the file.
That way, you don't need to try to go back to the right point in time - with a new copy of the file - you are starting with a clean slate.
Copy link to clipboard
Copied
There’s also revert()
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
app.activeDocument.revert();
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL