[GastForen Programme Print/Bildbearbeitung Adobe InDesign Javascript: Referenz auf vorhergenden Absatz

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

Javascript: Referenz auf vorhergenden Absatz

flobuc
Beiträge gesamt: 246

8. Sep 2008, 10:47
Beitrag # 1 von 12
Bewertung:
(3657 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo,

vielleicht weiss hier jemand einen Rat:
Ich möchte in einen Javascript einfach nur eine Referenz auf den vorhergenden Absatz bekommen.
Ich habe eine Referenz auf den aktuellen Absatz, ich hab eine Referenz auf die aktuelle Story. Es muss doch eine Möglichkeit geben dann direkt den vorhergenden Absatz zu referenzieren.

Meine aktuelle Lösung durchsucht jetzt die gesamte Story nach dem aktuellen Absatz und geht dann einen Absatz zurück. Funktioniert zwar ist aber von der Performance her, nicht so toll.

Gruss

Flo
X

Javascript: Referenz auf vorhergenden Absatz

Gerald Singelmann
  
Beiträge gesamt: 6269

8. Sep 2008, 10:56
Beitrag # 2 von 12
Beitrag ID: #365169
Bewertung:
(3652 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
(Wann ist Martin eigentlich wieder da? Der schüttelt so was immer aus dem Handgelenk ;) )

Wenn Sie sagen "Ich habe den Absatz" kann das zweierlei bedeuten:
- "Ich habe eine Referenz auf den Absatz und damit auf seinen index"
- "Ich weiß, der wievielte Absatz in der Story es ist"

Wenn letzteres, ist die Frage sehr leicht beantwortet. Dann ist der Absatz davor einfach myStory.paragraphs[n-1]

Falls ersteres (wahrscheinlich), wirds schwieriger, da der index eines Absatzes nicht sagt, der wievielte Absatz in der Story das ist, sondern den index des ersten Buchstabens im Absatz angibt.

Ich weiß da auch keinen besseren Weg, als in einer Schleife durch die Story zu gehen, bis der index des ersten Zeichens gleich dem index des Absatzes ist.


als Antwort auf: [#365166]

Javascript: Referenz auf vorhergenden Absatz

zaphodbeeblebroxx
Beiträge gesamt: 408

8. Sep 2008, 11:00
Beitrag # 3 von 12
Beitrag ID: #365170
Bewertung:
(3645 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
 
Hallo Flo,

versuchs mal mit:

Code
parentStory.paragraphs.previousItem(myParagraph); 


wobei das von der Performance meines wissens langsamer ist als die Variante, die Herr Singelmann beschrieben hat.


als Antwort auf: [#365169]

Javascript: Referenz auf vorhergenden Absatz

Martin Fischer
  
Beiträge gesamt: 12783

8. Sep 2008, 11:43
Beitrag # 4 von 12
Beitrag ID: #365181
Bewertung:
(3628 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo,

Antwort auf [ Matthias ] wobei das von der Performance meines wissens langsamer ist als die Variante, die Herr Singelmann beschrieben hat.


Das kann ich unbedingt bestätigen.
Siehe http://www.hilfdirselbst.ch/..._P360958.html#360958.
Dort auch eine alternative Funktion zu nextItem() - analog dazu wäre diese Funktion für previousItem() anzupassen.


Antwort auf [ Gerald ] Ich weiß da auch keinen besseren Weg, als in einer Schleife durch die Story zu gehen, bis der index des ersten Zeichens gleich dem index des Absatzes ist.

Man könnte alternativ - wie im Link oben gezeigt - einen Bereich itemByRange() vom Anfang der Story bis zum Index des Absatzes definieren und die darin enthaltenen Absätze zählen.


als Antwort auf: [#365170]
(Dieser Beitrag wurde von Martin Fischer am 8. Sep 2008, 12:00 geändert)

Javascript: Referenz auf vorhergenden Absatz

flobuc
Beiträge gesamt: 246

8. Sep 2008, 11:50
Beitrag # 5 von 12
Beitrag ID: #365182
Bewertung:
(3622 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Vielen Dank für die schnellen Antworten.

Die Methode von Matthias funktioniert zwar, ist aber wie von ihm schon angedeutet nochmal wesentlich langsamer als die Schleifenvariante.
Im meinen Falle liefert der Profiler folgenden Werte:
Schleife: 5315375
direkter Zugriff: 17779853

Dann lass ich die Schleife, mal so stehen.

Danke.

Flo


als Antwort auf: [#365170]

Javascript: Referenz auf vorhergenden Absatz

Martin Fischer
  
Beiträge gesamt: 12783

8. Sep 2008, 12:06
Beitrag # 6 von 12
Beitrag ID: #365188
Bewertung:
(3609 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Offensichtlich hatte ich im angegebenen Thread mit den oben angepriesenen Funktionen gegeizt.
Deswegen seien sie hier nachgereicht:

Code
function previousPara( onePara ) 
{
var myParaIndex = onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1 ).paragraphs.length;
var prePara = onePara.parentStory.paragraphs[myParaIndex - 2];
return prePara;
}

function nextPara( onePara )
{
var myParaIndex = onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1 ).paragraphs.length;
var nePara = onePara.parentStory.paragraphs[myParaIndex];
return nePara;
}


Die Funktionen erwarten als Übergabeparameter ein Absatz-Objekt.
Eine Fehlerabfangroutine zur Reaktion auf ein fehlerhaftes Objekt ist nicht enthalten.


als Antwort auf: [#365182]

Javascript: Referenz auf vorhergenden Absatz

Gerald Singelmann
  
Beiträge gesamt: 6269

8. Sep 2008, 12:21
Beitrag # 7 von 12
Beitrag ID: #365190
Bewertung:
(3599 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Zitat Deswegen seien sie hier nachgereicht:

Ui, die sind ja wesentlich cleverer als per Schleife durchzugehen.

Mir fiel vorhin auf, dass ich bisher noch nie Benchmarks auf Scripts gelegt habe. Anbei mein Ansatz, wie man die Geschwindigkeit von Routinen messen kann:

Code
main(); 

function main() {
var a = app.documents[0].stories[0].paragraphs[0].index;
var aStory = app.activeDocument.stories[0];
var d1 = new Date();
var arrayA = loadByPrevious(aStory);
var d2 = new Date();
alert("Fill by previous in Sekunden: " + compareDates(d1,d2));

var d1 = new Date();
var arrayA = loadByOwn(aStory);
var d2 = new Date();
alert("Fill by own in Sekunden: " + compareDates(d1,d2));

var d1 = new Date();
var arrayA = loadByIndex(aStory);
var d2 = new Date();
alert("Fill by index in Sekunden: " + compareDates(d1,d2));


}

function loadByPrevious(aStory) {
var lastPar = aStory.paragraphs.lastItem();
var pIndexs = new Array();
var i = lastPar.index;
var pPar = aStory.paragraphs.previousItem(lastPar);
pIndexs.push(i);
while ( i > 0) {
i = pPar.index;
pIndexs.push(i);
pPar = aStory.paragraphs.previousItem(pPar);
}
return pIndexs;
}

function loadByOwn(aStory) {
var lastPar = aStory.paragraphs.lastItem();
var pIndexs = new Array();
var i = lastPar.index;
pIndexs.push(i);
var nPar = getPNumber(aStory, i);
var pPar = aStory.paragraphs[nPar-1];
while ( i > 0) {
i = pPar.index;
pIndexs.push(i);
nPar = getPNumber(aStory, i);
pPar = aStory.paragraphs[nPar-1];
}
return pIndexs;
}

function loadByIndex(aStory) {
var lastPar = aStory.paragraphs.lastItem();
var pIndexs = new Array();
var i = lastPar.index;
pIndexs.push(i);
var nPar = getPNumber(aStory, i);
var pPar = aStory.paragraphs[nPar-1];
while ( i > 0) {
i = pPar.index;
pIndexs.push(i);
nPar--;
pPar = aStory.paragraphs[nPar];
}
return pIndexs;
}

function getPNumber(aStory, anIndex) {
if (anIndex == 0) {
return 0;
} else {
nPars = aStory.paragraphs.length;
for (var n=1 ; n < nPars; n++) {
if (aStory.paragraphs[n].index >= anIndex) {
return n;
}
}
}
return -1;
}

function compareDates(d1, d2) {
// Gibt den Unterschied zwischen zwei Dates in Sekunden
var m1 = (d1.getHours() * 60 * 60000) + (d1.getMinutes()*60000) + (d1.getSeconds() * 1000) + d1.getMilliseconds();
var m2 = (d2.getHours() * 60 * 60000) + (d2.getMinutes()*60000) + (d2.getSeconds() * 1000) + d2.getMilliseconds();
return (m2 - m1) / 1000;
}



als Antwort auf: [#365188]

Javascript: Referenz auf vorhergenden Absatz

flobuc
Beiträge gesamt: 246

8. Sep 2008, 12:32
Beitrag # 8 von 12
Beitrag ID: #365191
Bewertung:
(3585 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Herr Fischer,

ich bin begeistert!!!
Ihre Lösung ist mit Abstand die Schnellste.
Profiler: 275295

Aber ganz ehrlich mit der Implementierung hab ich ein Problem:
ItemByRange gibt doch (laut Doku) ein normales JavaScript-Array zurück. In der Realität kommt aber ein einzelnes InsertionPoint-Objekt zurück. Versteh ich nicht, es müssten doch mehrere InsertionPoints zurückkommen. Vielleicht können Sie mir das nochmal erklären?

Vielen Dank!

Florian Buchner


als Antwort auf: [#365188]

Javascript: Referenz auf vorhergenden Absatz

Martin Fischer
  
Beiträge gesamt: 12783

8. Sep 2008, 12:47
Beitrag # 9 von 12
Beitrag ID: #365197
Bewertung:
(3578 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Florian,

die geposteten Funktionen geben ein Absatz-Objekt zurück.

> In der Realität kommt aber ein einzelnes InsertionPoint-Objekt zurück.

Was ist die Realität?
'onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1 ).paragraphs.length' oder 'onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1 )'

Ersteres gibt die Anzahl der Absätze zurück.
Letzteres ein Objekt InsertionPoint mit vielen InsertionPoint-Kindern (schau mal nach den insertionPoints des zurückgegebenen insertionPoint-Objekts).

Praktisch hat mich das bislang nicht gestört.
Theoretisch hast Du mich jetzt etwas verunsichert: Statt den Kindern hätte ich auch eine Sammlung (von - bis) erwartet. Hm. Vielleicht weiß ein Philosoph mehr dazu. ;-)


als Antwort auf: [#365191]

Javascript: Referenz auf vorhergenden Absatz

flobuc
Beiträge gesamt: 246

8. Sep 2008, 14:11
Beitrag # 10 von 12
Beitrag ID: #365216
Bewertung:
(3549 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Herr Fischer,

vielen Dank für die Erklärung.
Tut mir leid das ich mich da unverständlich ausdrückte, ich meinte natürlich

onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1 )

Dieser Aufruf gibt also einen InsertionPoint mit vielen Child-InsertionPoints zurück.
Dann ist es also so, dass

onePara.parentStory.insertionPoints.itemByRange( 0, onePara.index + 1).paragraphs

auch die Kindelemente mit einschließt, das wusste ich nicht.
Vielen Dank für die Erkärung.

@Herrn Singelmann: Was die Profilierung angeht, muss ich sagen das ich immer den Standard-Profiler vom ESTK verwende.
Die genauen Zahlen kann man ignorieren, aber das Verhältnis lässt sich dadurch ganz gut ablesen. Gerade im Mengensatz haben wir hier oft Skripte die Laufzeiten von mehreren Stunden haben und da lohnen sich schon kleinste Einsparungen.
Wichtig ist nur das das Skript den auszumessenden Codeteil mehrfach durchläuft, da es anscheinend auch bei InDesign-Javascript eine Art JustInTime-Compiler gibt und dieser die HotSpots optimiert.

Mit freundlichen Grüßen


Florian Buchner


als Antwort auf: [#365197]

Javascript: Referenz auf vorhergenden Absatz

Martin Fischer
  
Beiträge gesamt: 12783

8. Sep 2008, 14:20
Beitrag # 11 von 12
Beitrag ID: #365218
Bewertung:
(3531 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
> Statt den Kindern hätte ich auch eine Sammlung (von - bis) erwartet.

Die Funktion itemByRange() liefert ein Objekt der Klasse, auf die sie angewendet wird.
Also InsertionPoint bei insertionPoints.itemByRange() oder Character bei characters.itemByRange().
Der Bereich spiegelt sich dann in den Kindern dieses Objekts.
Und zwar in den Kindern desselben Typs wie das Objekt selbst.
Sie sind als solche auch einzeln ansprechbar.

Was mich bei der Angelegenheit allerdings wundert ist, dass das über itemByRange() zurückgegebene Objekt Eigenschaften besitzt, die als Array zurückgegeben werden. Und zwar als Array mit der Länge 1! Haben die Zeichen in einem itemByRange()-Objekt verschiedene Schriftschnitte, wird nur der Schriftschnitt des ersten Zeichens zurückgegeben – und zwar als Eigenschaft des ersten Objekts des Arrays (mit der Länge 1).

Das itemByRange()-Objekt als solches scheint etwas außergewöhnlich und hat damit mein Interesse an einem Studium desselben über die praktische Anwendung hinaus geweckt.


als Antwort auf: [#365197]

Javascript: Referenz auf vorhergenden Absatz

Martin Fischer
  
Beiträge gesamt: 12783

8. Sep 2008, 15:24
Beitrag # 12 von 12
Beitrag ID: #365233
Bewertung:
(3515 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hi Gerald,

hab Dank für Deinen Ansatz und die Funktion compareDates().

Meine Stoppuhr sieht so aus:

Code
var t1 = zeitPunkt(); 
// do something
zeitStop();


function zeitPunkt()
{
var d = new Date()
return Math.round( d.getTime() / 100 )
}

function zeitStop()
{
var t2 = zeitPunkt();
var myTime =( t2 - t1 ) / 10;
if ( myTime >= 60 ) {
myMin = Math.floor( myTime / 60 );
mySec = myTime-myMin * 60;
myTime = myMin + ':' + mySec + ' Min.';
}
else
{
myTime += ' Sek.'
}
alert( 'Fertig!\rnach ' + myTime );
}



als Antwort auf: [#365190]
X