[GastForen Programme Print/Bildbearbeitung Adobe InDesign Skriptwerkstatt Interaktives Panel

  • Suche
  • Hilfe
  • Lesezeichen
  • Benutzerliste
Print/Bildbearbeitung - Photos, Layout, Design
Themen
Beiträge
Moderatoren
Letzter Beitrag

Interaktives Panel

tsone
Beiträge gesamt: 70

10. Jul 2017, 17:45
Beitrag # 1 von 35
Bewertung:
(11894 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Leute,

ich habe in InDesign ein eigenes Panel laufen, bei dem ich mit Buttons verschiedene JSX ausführen kann, die sich auf das geöffnete InDesign-Dokument auswirken.

Jetzt möchte ich aber, dass in dem Panel selber was passiert. Zum Beispiel, dass er mir im Panel den Namen des gerade ausgewählten Objektes anzeigt. Ich weiß, dass ich das auch über die Ebenen-Palette sehen kann - allerdings wird das unübersichtlich, wenn ich dort viele Ebenen habe, die teilweise zugeklappt sind.

Hat da jemand eine Idee?

Danke und Grüße
X

Interaktives Panel

drerol74
Beiträge gesamt: 507

12. Jul 2017, 00:46
Beitrag # 2 von 35
Beitrag ID: #558578
Bewertung:
(11422 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo,

um welches Panel handelt es sich denn, HTML? Bzw. welche InDesign-Version?

Schöne Grüße
Roland


als Antwort auf: [#558552]

Interaktives Panel

tsone
Beiträge gesamt: 70

12. Jul 2017, 08:15
Beitrag # 3 von 35
Beitrag ID: #558580
Bewertung:
(11239 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,

es handelt sich um InDesign CC 2017 also ein HTML-Panel.


als Antwort auf: [#558578]

Interaktives Panel

drerol74
Beiträge gesamt: 507

12. Jul 2017, 18:42
Beitrag # 4 von 35
Beitrag ID: #558599
Bewertung:
(10975 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
So sollte es gehen. Hier wrid als Beispiel nach Klick auf den Button der Constructor der aktuellen InDesign-Auswahl angezeigt:

JavaScript:

Code
(function () { 

'use strict';

var csInterface = new CSInterface();
var output = document.getElementById("constructor-name");

document.getElementById('test-button').addEventListener('click', function () {
csInterface.evalScript('__main()');
});

csInterface.addEventListener("custom_event", function(event) {
output.innerHTML = event.data;
});

}());



ExtendScript:

Code
function __main() { 

if(app.documents.length == 0) { return false; }

var _selection = app.selection;
if(!_selection) { return false; }

var _constructorName = _selection[0].constructor.name;

try {
var _externalObjLib = new ExternalObject("lib:\PlugPlugExternalObject");
} catch(_error) {
alert(_error);
}

if(!_externalObjLib) { return false; }

var _csxsEventObj = new CSXSEvent();

_csxsEventObj.type = "custom_event";
_csxsEventObj.data = _constructorName;
_csxsEventObj.dispatch();

return;
} /* END function __main */



index.html:

Code
<!doctype html> 
<html>

<head>
<meta charset="utf-8"/>
<title>Interakives Panel</title>
<link rel="stylesheet" href="css/styles.css"/>
</head>

<body>
<div id="content">
<h1 id="constructor-name">Constructor erscheint hier ...</h1>
<button id="test-button">Hier klicken</button>
</div>

<script src="js/libs/CSInterface.js"></script>
<script src="js/main.js"></script>
</body>
<html>



Die Webseite von Davide Barraca ist dazu sehr zu empfehlen, dort gibt es viele Beispiele zu ähnlichen Sachen. Und nicht zu vergessen sein Buch.

https://www.davidebarranca.com

Schöne Grüße
Roland


als Antwort auf: [#558580]

Interaktives Panel

tsone
Beiträge gesamt: 70

13. Jul 2017, 09:23
Beitrag # 5 von 35
Beitrag ID: #558610
Bewertung:
(10422 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,

kann ich das "JavaScript" mit in die "index.html" packen und das "ExtendScript" in eine JSX?

Meine aktuellen Scripte rufe ich so auf:

index.html
Code
<button id="btn_PNGTODESKTOP72" onClick="onClickButton('PNGTODESKTOP72')">72</button> 


export.jsx:
Code
$._ext_PNGTODESKTOP72={ 
run : function() {
/********** Replace below sample code with your own JSX code **********/
var Dateiname = app.activeDocument.name.split(".")[0];
var Buchstabe_klein = Dateiname.charAt(0).toLowerCase();
var Buchstabe_gross = Dateiname.charAt(0).toUpperCase();
app.pngExportPreferences.transparentBackground = true;
app.pngExportPreferences.exportResolution = 72;
app.pngExportPreferences.pngQuality = PNGQualityEnum.HIGH;
app.activeDocument.exportFile(ExportFormat.PNG_FORMAT, File(new File("~/Desktop/" + Dateiname + ".png")));
/************************************************************************/
return appName; }, };


Danke und Grüße


als Antwort auf: [#558599]

Interaktives Panel

tsone
Beiträge gesamt: 70

13. Jul 2017, 13:05
Beitrag # 6 von 35
Beitrag ID: #558619
Bewertung:
(10256 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Ah, hab mit ein bisschen Basteln was hinbekommen.

Jetzt muss das auch so funktionieren, dass ich nicht extra nen Button klicken muss. Sprich - wenn ich ein Objekt auswähle, soll er im Panel den Objekt-Namen anzeigen.


als Antwort auf: [#558610]

Interaktives Panel

drerol74
Beiträge gesamt: 507

13. Jul 2017, 14:33
Beitrag # 7 von 35
Beitrag ID: #558621
Bewertung:
(10188 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf: kann ich das "JavaScript" mit in die "index.html" packen


Du kannst den js-Code auch in dei Index-Datei schreiben. Bezüglich Wartung finde ich die Verlinkung und Auslagerung in eine eigene Datei aber praktischer.


Antwort auf: und das "ExtendScript" in eine JSX?


So war es gedacht ;)


Antwort auf: Jetzt muss das auch so funktionieren, dass ich nicht extra nen Button klicken muss. Sprich - wenn ich ein Objekt auswähle, soll er im Panel den Objekt-Namen anzeigen.


Mit dem EventListener »afterSelectionChanged«, meinst du das? Der Button war nur zur Demonstration.

Schöne Grüße
Roland


als Antwort auf: [#558619]

Interaktives Panel

tsone
Beiträge gesamt: 70

13. Jul 2017, 14:36
Beitrag # 8 von 35
Beitrag ID: #558622
Bewertung:
(10185 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hab ein wenig mit afterSelectionChanged rumgespielt.

Über das Panel passiert gar nichts. Über ein externe Skriptdatei bekomme ich auch bei verschiedenen eventListener nur Fehlermeldungen, dass das Objekt nicht mehr verfügbar ist.


als Antwort auf: [#558619]

Interaktives Panel

Dirk Becker
Beiträge gesamt: 193

13. Jul 2017, 20:12
Beitrag # 9 von 35
Beitrag ID: #558632
Bewertung:
(9948 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Zitat Fehlermeldungen, dass das Objekt nicht mehr verfügbar ist


Vermutlich fehlt da die targetengine Anweisung.
https://www.google.de/...ndesign+targetengine


als Antwort auf: [#558622]

Interaktives Panel

tsone
Beiträge gesamt: 70

14. Jul 2017, 07:18
Beitrag # 10 von 35
Beitrag ID: #558634
Bewertung:
(9529 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Dirk,

mit
Code
#targetengine "session" 

hat es geklappt. Allerdings bekomme ich beim InDesign öffnen, dass "undefined is not an object" ist.
Vermute mal, dass das kommt, weil noch kein Objekt ausgewählt ist.

Außerdem muss ich erst Rolands Button zweimal im Panel klicken, bis auch der "afterSelectionChanged" funktioniert.

Danach

Aber vielen Dank euch für die Hilfe!!!


als Antwort auf: [#558632]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

14. Jul 2017, 09:58
Beitrag # 11 von 35
Beitrag ID: #558636
Bewertung:
(9391 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf [ tsone ] … Allerdings bekomme ich beim InDesign öffnen, dass "undefined is not an object" ist. Vermute mal, dass das kommt, weil noch kein Objekt ausgewählt ist.


Hallo tsone,
was heißt "beim InDesign öffnen" genau?
Du startest InDesign und erwartest, dass die Arbeit mit app.selection funktioniert? Genau das ist aber nicht der Fall solange kein Dokument geöffnet ist.

Lass mal das hier als Startup-Script laufen:

Code
#targetengine uwe-test 

app.addEventListener("afterSelectionChanged", doSomething);

function doSomething(evt)
{

// THIS WILL FAIL AFTER STARTUP OF INDESIGN:
// Do nothing if nothing is selected:
if(app.selection.length == 0){return};

// OPTIONAL:
// Do nothing if text is selected:
if(app.selection[0].hasOwnProperty("baselineShift")){return};

// Final action:
alert(app.selection.length);
};


Und dann ändere das Startup-Script zu dem hier:

Code
#targetengine uwe-test 

app.addEventListener("afterSelectionChanged", doSomething);

function doSomething(evt)
{
// Do nothing if no document is open:
if(app.documents.length == 0){return};

// OPTIONAL:
// Do nothing if nothing is selected:
if(app.selection.length == 0){return};

// OPTIONAL:
// Do nothing if text is selected:
if(app.selection[0].hasOwnProperty("baselineShift")){return};

// Final action:
alert(app.selection.length);
};


Dazwischen natürlich InDesign neustarten.

[b]Warum versuche ich Textauswahlen auszublenden?
Der Listener liefert mit Textauswahlen quasi jeden "Pups". Also zum Beispiel wenn die Einfügemarke im Text bewegt wird. Oder wenn der Anwender Text tippt, dann gilt bei jeder neuen Einfügemarke: "Hallihallo! Die Auswahl hat sich geändert!" Wirklich nach jedem Zeichen! Kann nervig werden. Braucht man jetzt nicht so rigoros umsetzen wie ich das hier mache, aber man sollte darauf gefasst sein, dass jede Menge Meldungen in kurzer Zeit auf einen zukommen können.

Es wäre zu überlegen, ob Du überhaupt mit afterSelectionChanged arbeiten solltest.
Stattdessen könntest Du ein [b]IdleTask der app hinzufügen und dem einen listener für [b]IdleEvent.ON_IDLE mit einer entsprechenden Handler-Funktion mitgeben, die die Auswahl prüft und auswertet. Da könnte man sogar einen Intervall für's Nachschauen einbauen.

Doku hier:
http://jongware.mit.edu/...c_IdleTasks.html#add
http://jongware.mit.edu/...6js/pc_IdleTask.html

Schnipsel da:

Code
var newIdleTask = app.idleTasks.add 
(
{
name : "DoSomethingIfIdleEverySecond" ,
sleep : 1000
}
);

var onIdleListener = newIdleTask.addEventListener( IdleEvent.ON_IDLE , doSomeThing , false);

function doSomeThing(evt)
{
// Your functionality goes here:
if(app.documents.length == 0){return};
if(app.selection.length > 1)
{
// Notify my panel
}

};



als Antwort auf: [#558634]

Interaktives Panel

tsone
Beiträge gesamt: 70

14. Jul 2017, 10:33
Beitrag # 12 von 35
Beitrag ID: #558637
Bewertung:
(9365 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Uwe,

das mit dem IdleTask schaue ich mir mal.

Danke und Grüße
Timo


als Antwort auf: [#558636]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

14. Jul 2017, 11:16
Beitrag # 13 von 35
Beitrag ID: #558639
Bewertung:
(9335 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Timo,

ergänzend zu dem vorher gesagten:

1. Ich hatte ja nur vermutet, dass Du bei der Aktivierung des Listeners kein Dokument offen hast. Oder den Fall: Der Benutzer schließt alle Dokumente. Dann sollte der Listener ja ohne Fehlermeldung einfach weiterlaufen.
Bis der Benutzer entscheidet das Panel zu schließen.

2. Um eine echte Fehlerbehandlung zu machen, könntest Du mit try-catch arbeiten um den Fehler zu untersuchen.

Falls kein Dokument geöffnet ist, wirft das hier einen Fehler:
Code
app.selection.length 


Welche Fehlernummer?

Code
try 
{
app.selection.length;
}
catch(e)
{
alert(e.number);
};

// 90884


Du könntest darauf reagieren, und den weiteren Code nicht ausführen.
Ob das für alle Situationen reicht? Möglicherweise nicht.

Code
#targetengine uwe-test 

app.addEventListener("afterSelectionChanged", doSomething);

function doSomething(evt)
{
try
{
app.selection.length;
}
catch(e)
{
if(e.number == 90884)
{

// Known error.

// e.message
// "Es sind keine Dokumente geöffnet."

// app.findKeyStrings("Es sind keine Dokumente geöffnet.")
// $ID/NoDocumentOpenError

return
};
else
{
alert( "Error: "+e.number +"\r"+ e.message );
return
};
}
};


Im Falle des Schließens eines Dokuments bekomme ich einen weiteren Fehler geworfen: "Es sind keine Dokumentenfenster geöffnet" mit Fehlernummer 90886.

Den könntest Du dann auch in die Kategorie der "bekannten" Fehler einordnen.
Vielleicht treten ja noch andere auf, die Du behandeln möchtest.

Also: Testen!


als Antwort auf: [#558637]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

15. Jul 2017, 09:31
Beitrag # 14 von 35
Beitrag ID: #558650
Bewertung:
(8490 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Kleine Korrektur meiner Formulierung:

"Es sind keine Dokumentenfenster geöffnet" muss heißen:
"Es sind keine Dokumentfenster geöffnet."
$ID/NoWindowOpenError

Dieser Fehler wird auch geworfen, wenn Du beispielsweise mit mehreren Fenstern eines Dokuments arbeitest und eines davon schließt. Ob Textansicht oder Layoutansicht macht keinen Unterschied.

Die Formulierung der Meldung ist ein wenig widersprüchlich. Könnte etwas präziser sein. "Das Fenster der Auswahl ist nicht mehr geöffnet." wäre vielleicht besser…

Experimentiere auch mal mit dem Seitenwerkzeug während der Listener läuft.
Weiss nicht, ob Du auch ausgewählte Seiten in Deinem Panel aufnehmen möchtest.


als Antwort auf: [#558639]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

17. Jul 2017, 16:55
Beitrag # 15 von 35
Beitrag ID: #558671
Bewertung:
(7523 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf: Hallo Uwe,

das mit dem IdleTask schaue ich mir mal.

Danke und Grüße
Timo


Hallo Timo,
hast Du neue Erkenntnisse?

afterSelectionChanged vs IdleTask

Die Hauptunterschiede dürften sein:

1. Mit der IdleTask fragst Du, bzw. kannst Du im Intervall abfragen wie es um die Auswahl bestellt ist. Und da InDesign im Moment der Abfrage "idle" ist, also nichts macht, wird der Anwender auch nicht ausgebremst. So jedenfalls die Theorie.

2. Mit dem afterSelectionChanged eventhandler wirst Du vermutlich stärker filtern müssen, wenn es um Textauswahlen geht. Es steht zu befürchten, dass das auf die Performance gehen könnte. Davon abgesehen: Du kannst den auch an das activeDocument hängen und musst ihn nicht unbedingt an der Application festmachen.

Was bei beiden passieren kann:
Wenn Du mal einen Zähler mitlaufen lässt, wirst Du feststellen, dass der handler mal "durchrutscht". Soll heißen, dass manche events zwar registriert, der Zähler hochgezählt, die Aktion im handler aber nicht ausgeführt wird. Ist mir bei meinen Tests jedenfalls so ergangen.


als Antwort auf: [#558637]

Interaktives Panel

tsone
Beiträge gesamt: 70

17. Jul 2017, 17:49
Beitrag # 16 von 35
Beitrag ID: #558672
Bewertung:
(5060 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Uwe,

ich habe mich noch nicht weiter damit beschäftigen können. Scheint aber ne Wissenschaft für sich zu sein.

Muss mir noch überlegen, ob es für mich so überhaupt praktikabel ist, bzw. ob es meinen Arbeitsfluss unterstützt.

Trotzdem schon mal besten Dank an alle für die tolle Hilfe.

Grüße
Timo


als Antwort auf: [#558671]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

18. Jul 2017, 11:43
Beitrag # 17 von 35
Beitrag ID: #558682
Bewertung:
(4853 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Timo,
ja, das ist 'ne "Wissenschaft für sich"…

Ich würde mich jedenfalls auf regen Gedankenaustausch freuen, wenn Du Dich weiterhin mit diesem Thema beschäftigst. Der Testaufwand ist nicht unerheblich.


als Antwort auf: [#558672]

Interaktives Panel

drerol74
Beiträge gesamt: 507

18. Jul 2017, 13:01
Beitrag # 18 von 35
Beitrag ID: #558683
Bewertung:
(4828 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Uwe,

ich hab's am Wochenende auch nochmal mit »After Selection Changed« ausprobiert, bei mir funktioniert das hier:

https://www.rolanddreger.net/...hp/s/5hpilI4FGNAQ6QT

index.html

Code
<!doctype html> 
<html>
<head>
<meta charset="utf-8"/>
<title>Interakives Panel</title>
<link rel="stylesheet" href="css/styles.css"/>
</head>
<body>
<div id="content">
<h1 id="constructor-name">Constructor erscheint hier ...</h1>
</div>
<script src="js/libs/CSInterface.js"></script>
<script src="js/main.js"></script>
</body>
<html>


indesign.jsx

Code
unction __main() { 

try {
var _externalObjLib = new ExternalObject("lib:\PlugPlugExternalObject");
} catch(_error) {
alert(_error);
}

if(!_externalObjLib) { return false; }

app.addEventListener(Application.AFTER_SELECTION_CHANGED, __afterSelectionChangeHandler);

return;
} /* END function __main */



function __afterSelectionChangeHandler(_event){

if(app.documents.length === 0 || app.layoutWindows.length === 0) { return false; }

var _selection;
var _constructorName;

_selection = app.selection;

if(!_selection || _selection.length === 0) {
_constructorName = "Es ist nichts ausgewählt.";
} else {
_constructorName = _selection[0].constructor.name;
}

var _csxsEventObj = new CSXSEvent();

_csxsEventObj.type = "idSelectionChanged";
_csxsEventObj.data = _constructorName;
_csxsEventObj.dispatch();

return;
} /* END function __afterSelectionChangeHandler */



main.js

Code
(function () { 

'use strict';

var _csInterface = new CSInterface();
var _output = document.getElementById("constructor-name");

_csInterface.addEventListener("idSelectionChanged", function(_event){
_output.innerHTML = _event.data;
});

_csInterface.evalScript("__main()");

}());


Schöne Grüße
Roland


als Antwort auf: [#558682]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

18. Jul 2017, 20:00
Beitrag # 19 von 35
Beitrag ID: #558691
Bewertung:
(4746 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,
ja, ich dachte auch erst, dass das so funktioniert.

Teste mal mit dem Story-Editor oder mit einem zweiten Fenster des gleichen Dokuments. Schließe dann den Story-Editor oder das zweite Fenster. Das wird einen Fehler werfen, den Du nicht abfängst.

Ich denke, dass wir beim afterSelectionChanged eventhandler nicht um ein ordentliches try/catch herumkommen.

Hier mal ein ScriptUi-Window vom Typ Palette, das dies mit Deinem Code verdeutlicht:

Code
#targetengine uwe 

var c = 0;
var _constructorName = "Es ist nichts ausgewählt.";

var w = new Window("palette");
var myStaticText = w.add ("statictext", [0,0,200,50], c+" : "+_constructorName , {multiline: true});
w.show();

app.addEventListener(Application.AFTER_SELECTION_CHANGED, __afterSelectionChangeHandler);

function __afterSelectionChangeHandler(_event){

if(app.documents.length === 0 || app.layoutWindows.length === 0) { return };

var _selection;
var _constructorName;

_selection = app.selection;

if(!_selection || _selection.length === 0) {
_constructorName = "Es ist nichts ausgewählt.";
} else {
_constructorName = _selection[0].constructor.name;
}

myStaticText.text = c+" : "+_constructorName;
c++;
return;
} /* END function __afterSelectionChangeHandler */



als Antwort auf: [#558683]

Interaktives Panel

drerol74
Beiträge gesamt: 507

18. Jul 2017, 23:26
Beitrag # 20 von 35
Beitrag ID: #558693
Bewertung:
(4709 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Du hast recht Uwe, da hat es was. Den Texteditor könnte man noch mit instanceof LayoutWindow abfangen, aber damit gibt es dann einen Fehler bei app.activeWindow.

Ich habe es jetzt mal damit versucht:

Code
_selection = app.layoutWindows[0].selection; 


statt

Code
_selection = app.selection; 



Mit dem Texteditor wird dann halt die aktuelle Auswahl nicht angezeigt. Muss mir das aber auch noch mal genauer ansehen, wenn etwas mehr Zeit ist.


Schöne Grüße
Roland


als Antwort auf: [#558691]

Interaktives Panel

drerol74
Beiträge gesamt: 507

19. Jul 2017, 00:26
Beitrag # 21 von 35
Beitrag ID: #558694
Bewertung:
(4686 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Oder gleich das »layout« weglassen ...

Code
_selection = app.windows[0].selection; 



als Antwort auf: [#558693]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

19. Jul 2017, 07:13
Beitrag # 22 von 35
Beitrag ID: #558695
Bewertung:
(4618 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,
was stört Dich an einem try/catch, das die beiden bekannten Fehler $ID/NoDocumentOpenError 90884 und $ID/NoWindowOpenError 90886 erkennt und abfängt und nur bei neuen Fehlern beispielsweise protokolliert?


als Antwort auf: [#558694]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

19. Jul 2017, 07:41
Beitrag # 23 von 35
Beitrag ID: #558696
Bewertung:
(4615 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf: Oder gleich das »layout« weglassen ...

Code
_selection = app.windows[0].selection; 



Hallo Roland,
habe ich mal getestet.
Funktioniert tadellos.

EDIT:
Leider doch nicht. Hab' mich zu früh gefreut.
Mag an der Implementierung liegen.


als Antwort auf: [#558694]
(Dieser Beitrag wurde von Uwe Laubender am 19. Jul 2017, 07:57 geändert)

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

19. Jul 2017, 08:44
Beitrag # 24 von 35
Beitrag ID: #558697
Bewertung:
(4603 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Es hatte an der Implementierung gelegen.

Hier die Version, die funktioniert.
Anmerkung: Ich benutze ein ScriptUI-Fenster vom Typ "palette" mit einem "statictext"-Element, das einen Rollbalken aufweist.

Der Rollbalken funktioniert mit CS6.
Aber nicht mehr mit CC oder höher.

Die Auswertung im Fenster enthält einen Zähler plus den Konstruktornamen aller ausgewählten Objekte. Das ist noch nicht sehr aussagekräftig für einen Anwender, dient nur dazu, das Konstrukt zu testen.

Code
#targetengine rolandsIdea 

var c = 0;

var w = new Window("palette");
var myStaticText =
w.add
(
"statictext",
[0,0,250,100],
c+" : "+"Es ist nichts ausgewählt." ,
{
multiline: true ,
scrolling : true // Will not work in CC and above. No scroll bar available.
}
);

w.show();

app.addEventListener(Application.AFTER_SELECTION_CHANGED, writeSelectionToPalette );

function writeSelectionToPalette(evt)
{
// Roland's idea:
if( app.documents.length == 0 || app.windows.length == 0 )
{
myStaticText.text = c+" : "+"Es ist nichts ausgewählt. Event A."
c++;
return
};
// Roland's idea:
var selection = app.windows[0].selection;

var result = [];

if(selection.length == 0)
{
myStaticText.text = c+" : "+"Es ist nichts ausgewählt. Event B." ;
c++
return
};

for(var n=0;n<selection.length;n++)
{
result[n] = c+" : "+selection[n].constructor.name
};

myStaticText.text = result.join("\r");

c++;
return;
};



Wobei ich sagen muss, dass ich mir noch nicht ganz sicher bin, weshalb das funktioniert und der Fehler $ID/NoWindowOpenError mit Nummer 90886 nicht geworfen wird.

Beim Schließen eines Storyeditor-Fensters konnte ich diesen in früheren Versionen provozieren. Diesmal nicht.


als Antwort auf: [#558696]

Interaktives Panel

drerol74
Beiträge gesamt: 507

19. Jul 2017, 23:28
Beitrag # 25 von 35
Beitrag ID: #558710
Bewertung:
(4540 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf: was stört Dich an einem try/catch, das die beiden bekannten Fehler $ID/NoDocumentOpenError 90884 und $ID/NoWindowOpenError 90886 erkennt und abfängt und nur bei neuen Fehlern beispielsweise protokolliert?


An sich spricht – denke ich – in diesem Fall nichts dagegen, mit try/catch den Fehler zu umgehen. Wenn das mit windows[0].selection ginge, wäre es halt kürzer.


Antwort auf: Wobei ich sagen muss, dass ich mir noch nicht ganz sicher bin, weshalb das funktioniert und der Fehler $ID/NoWindowOpenError mit Nummer 90886 nicht geworfen wird.



Ich hab testweise an windows[0] und windows[1] (bei 2 Fenstern eines Dokuments) die EventListeners AFTER_ACTIVATE und BEFORE_DEACTIVATE angehängt.

Beim Schließen von windows[1] feuert zuerst AFTER_SELECTION_CHANGED. app.selection ergibt zu diesem Zeitpunkt schon einen Fehler.

Code
app.windows[0].selection.toSource() // Ergebnis: [] 
app.windows[1].selection // Fehler: Object is invalid
app.windows[1] == null // Ergebnis: true


Danach löst BEFORE_DEACTIVATE von windows[1] aus und daraufhin AFTER_ACTIVATE von windows[0]. In Folge ist app.selection dann wieder gültig.

Das ist jetzt auch nur Spekulation, aber app.selection könnte eigentlich über windows[1] auf die aktuelle Auswahl zugreifen. Als aktives Fenster wird noch app.windows[1] geführt, obwohl es gar nicht mehr aktiv ist. Dieser Fehler wird aber in app.selection nicht abgefangen und bleibt es dann hängen.

app.windows[0].selection ist allerdings zu jedem Zeitpunkt gültig, egal, ob jetzt ein oder zwei Fenster geöffnet sind oder welches gerade den Index 0 hat.

Ich denke, das ist einfach ein blöder Bug.

Schöne Grüße
Roland


als Antwort auf: [#558697]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

20. Jul 2017, 22:22
Beitrag # 26 von 35
Beitrag ID: #558718
Bewertung:
(4440 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,
hab Dank für's Testen. Ich muss aber mal nachfragen.

Zitat von Roland Ich hab testweise an windows[0] und windows[1] (bei 2 Fenstern eines Dokuments) die EventListeners AFTER_ACTIVATE und BEFORE_DEACTIVATE angehängt.


Ok.

Zitat von Roland Beim Schließen von windows[1] feuert zuerst AFTER_SELECTION_CHANGED. app.selection ergibt zu diesem Zeitpunkt schon einen Fehler.


Beim Schließen von windows[1] ? Also dasjenigen Fensters, das nicht das aktive ist? Das würde ich mal genauer begutachten wollen. Nur um nachzuvollziehen, wie Dein Versuchsaufbau war.

Hast Du das windows[1] per Mausklick über das UI geschlossen oder per Skriptbefehl mit windows[1].close() ?

Falls per Mausklick, wird ja dann windows[1] vermutlich kurzfristig zum aktiven Fenster.
Und erhält somit den index 0. Oder auch nicht. Siehe die Fälle A und B weiter unten.

Wir sollten an dieser Stelle erstmal Begrifflichkeiten klären.
Wenn Du von windows[0] und windows[1] sprichst, dann sprichst Du immer über die gleichen Fenster, oder?

Also Beispiel:

Dokument geöffnet. Zwei Fenster des gleichen Dokuments geöffnet.
Fenster 1: windows[0], das aktive Fenster mit Namen: Unbenannt-1:1 @ 50%
Fenster 2: windows[1], das nicht aktive Fenster: Unbenannt-1:2 @ 50%

Du schließt nun Fenster 2 per Mausklick. Wie?

A. Mit 2 Mausklicks?
Klick ins Fenster, um es dann mit einem zweiten Mausklick zu schließen?
Der Name von Fenster 1 ändert sich zu: Unbenannt-1 @ 53%

B. Mit 1 Mausklick?
Klick in das x des Tabs von Fenster 2 ?
Der Name von Fenster 1 ändert sich zu: Unbenannt-1 @ 53%

A. und B. könnten unterschiedliche Reihenfolgen von events auslösen.
Im Fall A ändert sich auch der Index des Fensters bis zum Zeitpunkt des Schließens zwingend. Bei B nicht.

Und ein weiterer Unterschied könnte sein, wenn Fenster 2 per methode close() geschlossen wird.
Könnte aber auch mit Fall B abgedeckt sein.

Vielleicht hab' ich ja am Wochenende ein weing Zeit, das genauer zu untersuchen.
Ich hoffe, mit meinen Fragen oder Bemerkungen nicht allzusehr zu verwirren.


als Antwort auf: [#558710]

Interaktives Panel

drerol74
Beiträge gesamt: 507

21. Jul 2017, 00:46
Beitrag # 27 von 35
Beitrag ID: #558719
Bewertung:
(4421 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Uwe,

zur späten Stunden nur ganz kurz zum Ablauf:

Ich hab in meinem Fall dem linken Fenster (zu Beginn aktiv) durch das Skript Window.AFTER_ACTIVATE angehängt und dem rechten Fenster Window.BEFORE_DEACTIVATE (beide gleiches Dok). Dann wurde das rechte Fenster aktiviert und über das UI (x) geschlossen.

Die Überlegung war einfach die, dass immer eines der Fenster den Index 0 aufweisen muss, auch wenn dieser zwischen den Fenstern wechselt.

Ich muss mich jetzt für ein paar Tage aus der Diskussion ausklinken, Urlaub \o/, bin eigentlich schon gar nicht mehr da ;) Vielleicht hast du bis dahin schon Genaueres herausgefunden.

Schöne Grüße
Roland


als Antwort auf: [#558718]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

24. Jul 2017, 08:15
Beitrag # 28 von 35
Beitrag ID: #558734
Bewertung:
(4162 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Roland,
danke für die genauere Beschreibung.

Bei mir sieht es allerdings auch so aus als könnte ich mich die nächsten 14 Tage kaum um den Fall kümmern.

Aber vielleicht geht ja Timo noch mal ran an die Sache.

Dir wünsche ich einen schönen Urlaub!
Bei mir steht ein Umzug an. Zwar in der gleichen Stadt, aber trotzdem zeit- und nervenaufreibend. Lebe im Moment in einer Baustelle. Und das kann man wortwörtlich so nehmen.


als Antwort auf: [#558719]

Interaktives Panel

Stephan_M
Beiträge gesamt: 480

21. Feb 2018, 00:07
Beitrag # 29 von 35
Beitrag ID: #562510
Bewertung:
(2127 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Uwe,

dieses Thema trifft genau mein Problem, bei dem ich auch gerade hänge. Der "AfterSelectionChange"-Event tritt ein, wenn jemand ein Fenster schliesst - "app.selection" ist dann im EventHandler schon nicht mehr gültig. Gleiches Spiel mit app.activeDocument.
Du hast oben diese Try/Catch-Anweisung vorgeschlagen, um den Handler-Fehler abzufangen ... nur, bei mir stürtzt Indesign dann ab, wenn er es 'tried'! Läuft das bei Dir? Magst Du mir helfen?

(Ich werde wohl auch auf das Idle-Event gehen. Meh! Ist halt nicht so Echt-Zeit, aber wohl sinnvoll.)

Liebe Grüße,
Stephan

Hier mein Test-Script:
Code
#targetengine miscellaneous 
var w = new Window ("palette { text: 'Test Palette', preferredSize: [220,16], alignChildren:['fill','top']}");
w.sText = w.add( "statictext", undefined, 'Tell Selection' );

function getParas() {
if (app.documents.length == 0) {
desc = 'No documents are open.';
}
else {
try {
app.selection.length;
}
catch(e) {
if(e.number == 90884 || e.number == 90886) {
return "Closing"
};
else {
return "Error: "+e.number +"\r"+ e.message
};
}

try {
app.activeDocument;
}
catch(e) {
return "Error: "+e.number +"\r"+ e.message
};

var ad = app.activeDocument;
var s = app.selection;
}
return (s.length == 0)?('Nothing selected'):(s[0].constructor.name);
}


function updateSel() {
w.sText.text = getParas();
w.graphics.backgroundColor = w.graphics.newBrush (w.graphics.BrushType.SOLID_COLOR, [Math.random(), Math.random(), Math.random()]); // to show when updateSel is called
}


app.eventListeners.add("afterSelectionChanged", updateSel,{name:'paraStyleChanger_selChange'});

w.onClose = function() { app.eventListeners.itemByName('paraStyleChanger_selChange').remove();}
w.show();



als Antwort auf: [#558672]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

21. Feb 2018, 10:19
Beitrag # 30 von 35
Beitrag ID: #562511
Bewertung:
(2065 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Stephan,
deinen Code hab' ich noch nicht getestet.
Mit welchem InDesign hast Du's probiert?

Da bei Dir bereits bei app.selection.length == 0 der Absturz kommt, kann ich an dieser Stelle einen Bug vermuten. Vielleicht funktionieren alternative Schreibweisen und ein sich Herantasten?

Sollte keinen Unterschied machen, aber wer weiß?:
Code
app.properties.selection.toString() == "" 


Vielleicht hilf ja auch das event-Objekt zu untersuchen?
Möglich, dass da was Brauchbares vorhanden ist.

Code
function updateSel( event ) 
{
var x , e ;
for( x in event )
{
try{ $.writeln( x +"\t"+ event[x].toString() ) }
catch(e){ $.writeln( x +"\t"+ e.message ) };
};
};



als Antwort auf: [#562510]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

21. Feb 2018, 13:20
Beitrag # 31 von 35
Beitrag ID: #562514
Bewertung:
(769 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Stephan,
hab' mal einen Kurztest mit Deinem Code und InDesign CC 2018 gestartet.
Bisher keine Abstürze. Auch nicht nach Schließen von irgendwelchen Layout-Windows.

Problem allerdings: Das Dialogfeld kann hinter den Anwendungsrahmen geraten.


als Antwort auf: [#562510]

Interaktives Panel

Stephan_M
Beiträge gesamt: 480

21. Feb 2018, 23:54
Beitrag # 32 von 35
Beitrag ID: #562517
Bewertung:
(742 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Danke Uwe, für das Testen und den Hinweis daß es bei Dir läuft. Habe mich dadurch erst dran gemacht nach Außen zu schauen, zwei Plugins und drei Autostartskripte entfernt... am Ende war es Rorohikos "StoryParker", daß im Zusammenspiel mit dem Testskript Indesign reproduzierbar einfror. Schon komisch.

Jetzt kann ich weiter machen. Dein Abfangen/Umwandeln der Event-Error-Messages hat mir auch geholfen. Und jetzt teste ich mal parallel, ob's mit dem Idle-Task eh eine bessere Lösung wird.

Hast mir geholfen!

Herzliche Grüße,
Stephan


als Antwort auf: [#562514]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

22. Feb 2018, 07:49
Beitrag # 33 von 35
Beitrag ID: #562519
Bewertung:
(725 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Antwort auf: … am Ende war es Rorohikos "StoryParker", daß im Zusammenspiel mit dem Testskript Indesign reproduzierbar einfror. Schon komisch. …


Aha!
Na, dann würde ich mal Kris Coppieters von Rorohiko davon unterrichten.


als Antwort auf: [#562517]

Interaktives Panel

Stephan_M
Beiträge gesamt: 480

22. Feb 2018, 21:11
Beitrag # 34 von 35
Beitrag ID: #562538
Bewertung:
(689 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Mach ich.

Hier noch die schnelle rescourcenschonenden verquickung des 'idleTasks' mit 'afterSelectionChanged' ...

Wenn die Selection sich ändert geht eine Flagge hoch. Und beim ersten Leerlauf guckt der Eventhandler erstmal nach der Flagge ob's überhaupt eine Veränderung abzuarbeiten gab. Wenn sich die Selection also sehr schnell und häufig ändert, dann wird darauf frühestens beim nächsten Leerlauf reagiert. Das ist toll, bei z.B. Texteingaben (insertion points).

Danke dafür, Uwe!

Code
#targetengine miscellaneous 
var w = new Window ("palette { text: 'Test Palette', preferredSize: [220,16], alignChildren:['fill','top']}");

w.sText = w.add( "statictext", undefined, 'Tell Selection' );
w.sText.needs_update = new Boolean;

function getParas() {
if (app.documents.length == 0) {
return "No documents are open.";
}
else {
try {
var ad = app.activeDocument;
var s = app.selection;
}
catch(e) {
if(e.number == 90884 || e.number == 90886) {
return "Closed Window"
};
else {
return "Error: "+e.number +"\r"+ e.message
};
}
}
return (s.length == 0)?('Nothing selected'):(s[0].constructor.name);
}


function updateSel(event) {
if (w.sText.needs_update) {
w.sText.text = getParas();
w.graphics.backgroundColor = w.graphics.newBrush (w.graphics.BrushType.SOLID_COLOR, [Math.random(), Math.random(), Math.random()]); // to show when updateSel is called
w.sText.needs_update = false;
}
}

app.eventListeners.add("afterSelectionChanged", function (){w.sText.needs_update = true;},{name:'paraStyleChanger_selChange'});

app.idleTasks.add ({name : "paraStyleChanger_idleTask" , sleep : 1000 }).addEventListener( IdleEvent.ON_IDLE , updateSel , false);

w.onClose = function() {
app.idleTasks.itemByName('paraStyleChanger_idleTask').remove();
app.eventListeners.itemByName('paraStyleChanger_selChange').remove();
}
w.show();



als Antwort auf: [#562519]

Interaktives Panel

Uwe Laubender
Beiträge gesamt: 5316

23. Feb 2018, 10:10
Beitrag # 35 von 35
Beitrag ID: #562542
Bewertung:
(662 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Stephan,
kleine Anmerkung zu Deinen Skriptzeilen:

Du kannst die else-Ummantelung des folgenden Codes bei Deiner ersten if-Abfrage weglassen. Bei einem return wird der folgende Code nicht ausgeführt.

Ebenso innerhalb des catch(), da Du dort mit return "Closed Window" die folgenden Codeausführung unterdrückst.

Hab Dein Skript noch nicht laufen lassen.
Werde rückmelden, wenn mir noch was auffällt.


als Antwort auf: [#562538]
X