Skriptujeme InDesign (4): Základy JavaScriptu podruhé - Grafika.cz - vše o počítačové grafice

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Software

Skriptujeme InDesign (4): Základy JavaScriptu podruhé

Adobe InDesign sazba

23. ledna 2006, 00.00 | Již podruhé se v našem seriálu podíváme na to, jak programovat v obecném JavaScriptu.
Jsou vám pojmy jako podmínka, cyklus, funkce či pole neznámé? Pak právě pro vás je určen
tento náš výklad.

V druhé části našeho výkladu o obecném JavaScriptu se budeme opět věnovat řadě pojmů, bez kterých se neobejde prakticky žádný programovací jazyk. Zdůraznit přitom stejně jako minule musíme skutečnost, že náš výklad je oproti odpovídající specifikaci jazyka značně zjednodušený, a rozšiřujícímu samostudiu se zde rozhodně meze nekladou.

Podmínky: příkazy if a switch

Důležitým prvkem JavaScriptu jsou, stejně jako v jiných programovacích jazycích, tzv. kontrolní (jinak též řídící) struktury. Patří k nim i podmíněné příkazy, které, jak již název naznačuje, dovolují provádět určené úseky kódu pouze v určité situaci - tj. při splnění či nesplnění stanovené podmínky. Nejobvyklejším podmíněným příkazem je takto příkaz if/else. Jeho struktura (povšimněme si použití složených závorek uzavírající tzv. bloky výrazu) vypadá následovně:

if (podmínka)
{
příkazy JavaScriptu, které se provedou, je-li podmínka splněna
}
else
{
příkazy JavaScriptu, které se provedou, není-li podmínka splněna
}

Podmínkou se přitom rozumí výraz JavaScriptu, který vrací logickou hodnotu (tedy true či false). Typickým příkazem takovéhoto výrazu je porovnání, o kterém jsme blíže hovořili v minulé části. Porovnání přitom může být jednoduchým výrazem stejně dobře, jako výrazem velmi složitým, záleží zde samozřejmě na tom, co chceme porovnávat.

Příklad:

Vyzkoušejte následující skript a zkuste v něm měnit počáteční přiřazení hodnoty proměnné promenna. (Mimo hlavní výklad: povšimněte si příkazu alert, který je výborným prostředkem pro různé "výpisy ze skriptu", vhodné při ladění skriptů, interakci s uživatelem atd.):

var promenna=-1;
if (promenna<0)
{
alert("Hodnota je menší než nula, tak ji vynulujem");
promenna=0;
alert("Hodnota je tedy nyní "+promenna);
}
else
{
alert("Hodnota je kladná, tak ji necháme jak je");
}

Výše uvedená struktura if/else je nejobecnější a nemusí být nutně použita v daném tvaru. Jednak není předepsáno použití mezer, takže můžeme klidně psát i

if (podmínka)
{příkazy JavaScriptu, které se provedou, je-li podmínka splněna}
else
{příkazy JavaScriptu, které se provedou, není-li podmínka splněna}

atp. - formátování zde vychází s potřeby učinit kód přehlednější a tím pádem i preferencí daného uživatele. Dále je možno vypustit buďto blok příkazů za if a použít rovnou else, nebo naopak použít pouze první blok a blok else vynechat. Složené závorky za if či else lze vypustit tam, kde provádíme pouze jeden příkaz, přijde nám ale lepší je striktně používat.

Kontrolní struktury, a tedy i if/else, lze do sebe vnořovat (vkládat). Můžeme tedy takto dále větvit provedení kódu na základě určitých hodnot. Pozor ale na přehlednost a srozumitelnost: podle některých studií se kód už od více jak čtyř úrovní vnoření stává jen těžko pochopitelným (problematické ladění). V takovéto situaci lze vnořené podmínky nahradit třeba funkcemi, o kterých budeme hovořit dále.

Příklad vnořeného kódu (s jiným formátováním zápisu a použitím složené podmínky):

var promenna=9;
if ((promenna>=0) && (promenna<=10))
{alert("Číslo je z intervalu 0-10");}
else
      {if (promenna<0) {alert("Hodnota je záporná");}
      else{alert("Proměnná je kladná a větší jak 10");}
}

Jinou cestu, jak se vyhnout příliš mnoha if, poskytuje podmíněný příkaz switch. Jeho pomocí lze totiž kód větvit podle více možných hodnot. Obecná struktura tohoto příkazu vypadá následovně:

switch (výraz)
{
case hodnota1: kód, který se provede, pokud výraz nabude hodnoty hodnota1;
               break;
case hodnota2: kód, který se provede, pokud výraz nabude hodnoty hodnota2;
               break;
...
case hodnotan: kód, který se provede, pokud výraz nabude hodnoty hodnotan;
               break;
default: kód, který se provede, pokud výraz nenabyl žádných z výše uvedených hodnot; }

Výraz za switch zde přitom jednoznačně určuje hodnotu, podle které probíhají následující testy. Příkaz break použitý v jednotlivých case je volitelný, a znamená, že se má okamžitě vyskočit z bloku příkazu switch. pokud by nebyl uveden, provedl by se i následující kód. Klíčové slovo default se umisťuje na závěr bloku a nemusí tedy být ukončeno s pomocí break, jeho použití je volitelné.

Příklad:

var pozdrav="Dobrý den"; //vyzkousejte zde priradit ruzne formy pozdravu
switch (pozdrav)
{case "Ahoj": alert("Taky zdravim");
              break;
case "Nazdar": alert("No nazdar");
              break;
case "Dobrý den": alert("Dobrý");
              break;
default: alert(pozdrav+"? Tak tenhle pozdrav neznám.")
}

Cykly: for, while, do-while

Jinou řídící strukturou, umožňující nám ve skriptech provádět opakovaně tentýž úsek kódu, jsou tzv. cykly. Nejčastěji používaným bývá cyklus for. Jeho obecná struktura vypadá následovně:

for (počáteční výraz; podmínka; výraz pro zvýšení hodnoty)
{
příkazy, které se provedou - tzv. tělo cyklu
}

Počátečním výrazem obvykle bývá ve zvyku deklarovat proměnnou, která v cyklu poslouží coby tzv. čítač, tj. bude určovat počet opakování cyklu - počáteční výraz se provádí pouze jednou, před započetím cyklu. Příkazy cyklu se provádí tak dlouho, dokud je splněna daná podmínka, která se typicky váže k použití čítače. Po každém provedení těla cyklu se vyhodnotí výraz pro zvýšení hodnoty - typicky se provede zvýšení (nebo i snížení) čítače o zadanou hodnotu. Příkazy v těle cyklu mohou být libovolné, tj. může se jednat jak o delší sekvenci, obsahující třeba i další vnořené cykly, tak i o jednoduchý příkaz. Použít zde lze i příkaz break, který zajistí předčasné ukončení cyklu - obvykle pokud hodnota nějaké jiné proměnné než je čítač nabude díky manipulacím v rámci cyklu hodnoty, která je pro nás určitým způsobem žádoucí či nežádoucí.

Příklad:

Vyzkoušejte následující skript (a všimněte si - opět mimo hlavní výklad - použití speciálních znaků \t pro tabulátor a \n pro konec řádku, operátoru inkrementace ++ či způsobu, jakým měníme hodnotu proměnné retezec i s využitím hodnoty čítače):

var retezec="";
for (var i=1;i<10;i++)
{retezec = retezec+i+".\tHello World\n";}
alert(retezec);

Vyzkoušejte pak tentýž skript s následujícím nastavením cyklu

for (var i=10;i>0;i--)

Pro efektivní práci s for (resp. cykly jako takovými) je vhodné osvojit si několik návyků, které nám dovolí daný konstrukt používat efektivně a bezchybně. Především je třeba dávat pozor na vhodné pojmenování čítače: nic nebrání jednopísmennému pojmenování (typicky i, j atd. viz výše), které je v daném případě lépe akceptovatelné než při jiných použitích proměnných. Přesto je ale vhodnější použít takové popisné pojmenování čítače (třeba pocet_odstavcu, citac apod.), které vystihuje jeho význam (kód se stane srozumitelnějším a eliminuje se možnost nevhodné manipulace s čítačem).

Pozor dávat na to, abychom se nedostali do nekonečné smyčky, tj. nedefinovali takovou manipulaci s čítačem, která nikdy neskončí. Mimo samotného definování for lze zde takto typicky udělat tu chybu, že hodnotu čítače změníme někde v těle cyklu - čítač je totiž proměnná jako každá jiná a lze jej tedy v rámci cyklu používat (viz příklad výše), což je vlastnost užitečná a žádoucí, v daném případě nicméně zrádná. Obvyklým trikem eliminující daný problém je přiřazení hodnoty čítače v těle cyklu nové proměnné, kterou pak používáme všude tam, kde bychom použili čítač.

Příklad (úprava cyklu uvedeného výše):

var retezec="";
for (var i=1;i<10;i++)
{var cislo=i;
retezec = retezec+cislo+".\tHello World\n";}
alert(retezec);

Pokud pak vnořujeme cykly do sebe, měli bychom dbát na to, aby každý z nich používal vlastní, odlišně pojmenovaný čítač. Zejména při vnořování je také třeba ohlídat správné použití složených závorek. Nejjednodušší zde je hned při počátečním zápisu vložit obě závorky a ty pak teprve vyplnit daným kódem, hodně rovněž pomůže přehledné formátování kódu.

Dalším typem cyklu je while. Jeho struktura vypadá následovně:

while (podmínka){
příkazy, které se provedou - tzv. tělo cyklu
}

Jak je tedy vidět, k tomu, aby byl daný cyklus ukončen, je zapotřebí, aby příslušná nastavení proběhla v jeho těle, tj. příslušným způsobem musíme měnit například proměnnou, které se podmínka týká, jinak opět uvízneme v nekonečné smyčce. Jinak platí pro cyklus while obdobná pravidla jako pro for.

Příklad:

Výše uvedený skript pro for lze s pomocí while zapsat následovně:

var retezec="";
var i=1;
while (i<10){
retezec = retezec+i+".\tHello World\n";
i++;
}
alert(retezec);

Konečně je zde cyklus do-while. Jeho struktura je následující:

do {
příkazy, které se provedou - tzv. tělo cyklu
} while (podmínka)

Jak si tedy lze povšimnout, tento cyklus proběhne vždy alespoň jedenkrát (podmínka je uvedena až na konci, pokud má hodnotu true provede se daný cyklus znovu, jinak se jeho provádění ukončí). Pokud není nic takového zapotřebí, vystačíme si s předchozími typy cyklů, pro použití do-while pak platí stejné zásady, jaké jsme uvedli výše.

Příklad:

Výše uvedený skript pro for lze s pomocí zapsat následovně:

var retezec="";
var i=1;
do {
retezec = retezec+i+".\tHello World\n";
i++;
} while (i<10)
alert(retezec);

Funkce

U rozsáhlejších skriptů si lze povšimnout, že určitý úsek kódu se zde opakuje znovu a znovu na různých místech, přičemž rozdíly mohu být třeba jen v hodnotách, které se zpracovávají (typicky se to vztahuje k výpočtům). Ke zpřehlednění takovýchto skriptů se používá tzv. funkcí, které nám dovolují opakovaný úsek zapsat pouze jednou pod určitým názvem a pak jej pod tímto názvem opakovaně použít. Pro vytvoření, čili deklaraci funkce používáme následující kód:

function jméno_funkce (parametry)
{
příkazy, které se provedou - tělo funkce
return návratová_hodnota;
}

Ve skriptu je pak daná funkce použita (volána) příkazem

jméno_funkce(parametry);

Parametry (nebo jinak též argumenty) funkce jsou proměnné, jejichž prostřednictvím předáváme funkci určité hodnoty: význam je zde takový, že chceme zohlednit určité změny v těle kódu. Seznam parametrů je oddělen čárkami. Pro každý parametr je deklarována nová proměnná stejného jména jako je název parametru, s kterou pak v těle funkce pracujeme stejným způsobem, jako s jinou proměnnou. Použití parametrů je nepovinné, můžeme definovat i funkce, které jsou bez parametrů, v takovém případě použijeme prázdné závorky ().

Rovněž nepovinné, ale často používané, je nasazení příkazu return v těle funkce. Jedná se zde o příkaz, který vrací určitou, tzv. návratovou hodnotu coby výsledek volání funkce. Je-li tento příkaz použit, musí být umístěn na poslední řádek v těle funkce. Pokud funkce nějakou návratovou hodnotu vrací, lze ji volat ve skriptu všude obdobně, jako bychom přímo pracovali s hodnotou.

Příklad:

//deklarace funkce spoj_texty
function spoj_texty (retezec1,retezec2,retezec3)
{
var spojeni=retezec1+" "+retezec2+" "+retezec3;
return spojeni;
}


//volani funkce spoj_texty v ramci prikazu alert
alert(spoj_texty ("ahoj", "jak se", "máš?"));
//tady jeste jedno volani s prirazenim navratove hodnoty promenne
vysledek_spojeni=spoj_texty ("docela", "dobře", "")
alert(vysledek_spojeni);

Důležité jsou zásady pro práci s proměnnými. Pokud v těle funkce používáme název proměnné bez deklarace, pracujeme takto vlastně s tzv. globální proměnnou, která může existovat i mimo tělo funkce. Ne vždy je takováto manipulace žádoucí (může dojít k nechtěnému přepsání hodnot), a tak se doporučuje, aby všechny proměnné použité v těle funkce byly deklarovány (a to pokud možno - pro přehlednost - na začátku těla funkce). Tím se stanou tzv. lokálními a budou platné pouze v těle funkce.

Umístění deklarace funkce v rámci těla funkce není dáno nějak striktně, doporučuje se nicméně deklarovat všechny funkce pokud možno najednou a to na začátku skriptu. Pravidla pro pojmenování funkcí jsou pak stejné jako pro pojmenování proměnných. A mimochodem, není od věci poznamenat, že metody objektů, o kterých jsme hovořili dříve, jsou vlastně funkcemi, které jsou definovány pro daný objekt. Pro práci s metodami tedy platí v podstatě stejné zásady jako pro práci s funkcemi.

Pole

Aby byl náš výklad o základech JavaScriptu, na kterém budeme stavět v dalších částech, pokud možno úplný, musíme ještě (byť hodně ve stručnosti) rozhodně probrat pojem pole (array). Rozumí se jim speciální typ objektu, reprezentující kolekci určitých hodnot - tzv. prvků pole. InDesign a příslušné skripty používají pole (a příslušných nástrojů) všude tam, kde se pracuje s více prvky téhož typu, tedy třeba dokumenty, stránkami, odstavci apod. a také třeba výběry či souřadnicemi, navíc existují i jiné situace, ve kterých je využití polí ve skriptech žádoucí.

Příkaz pro vytvoření pole může vypadat takto:

název_objektu_pole=new Array (prvek1, prvek2,..., prvekn)

nebo takto

název_objektu_pole=new Array (počet_prvků_pole)

V obou případech se vytvoří pole, obsahující n-prvků, v prvním případě je již naplněno konkrétními hodnotami (prvek1, prvek2 atd.), v druhém případ je pouze provedena odpovídající deklarace.

Příklad:

moje_pole=new Array (1,2,3,6);

K prvkům pole pak lze přistupovat přes jejich celočíselný index uzavřený v hranatých závorkách, který udává pozici prvku v poli. V JavaScriptu se pole indexují od nuly, takže na první pole je odkazováno indexem [0], na druhý indexem [1] atp. Jednotlivé prvky se pak tedy odkazují výrazem

nazev_pole[index]

Příklad:

Výraz

moje_pole[1]

vrací v případě předchozího ukázkového pole hodnotu 2.

Manipulace s hodnotou daného prvku pole se pak provádí prostřednictvím přiřazení, takže lze typicky provést toto

název_pole[index]=nová_hodnota;

Příklad:

Stejné pole jako v příkladu výše vytvoříme i zápisem

moje_pole=new Array (4);
moje_pole[0]=1;
moje_pole[1]=2;
moje_pole[2]=3;
moje_pole[3]=6;

Mimo indexu lze využít k indexování polí i řetězce, danou problematiku nicméně probereme až někdy příště.

Při dalším zpracovávání polí se využívají různé jeho vlastnosti a metody. V případě vlastností je přitom nejdůležitější vlastnost length, která vrací délku pole. S jejím použitím lze snadno vybudovat cykly, které zpracují obsah pole.

Příklad:

var obsah_pole="";
moje_pole=new Array (1,2,3,6) ;
for (var count=0;count<moje_pole.length;count++)
{obsah_pole=obsah_pole+moje_pole[count];}
alert (obsah_pole);

Metody objektu pole zde probírat zatím nebudeme, vrátíme se k nim opět až v rámci pozdějšího výkladu (zejména o práci s textem v InDesignu).

Výraz with

Smysl pro úplnost nám také nedá, abychom na tomto místě nezmínili výraz with, bez kterého bychom se sami sice obešli, ne už tak jiní ale autoři (viz zejména příklady v uživatelské příručce skriptování v InDesignu), na jejichž kód zvídavý čtenář jistě dříve nebo později narazí, a tak považujeme za vhodné význam daného výrazu osvětlit.

Výraz with nám dovoluje zkrátit zápis kódu tím způsobem, že určuje výchozí objekt, ke kterému se vztahuje sada určitých příkazů. Jeho použití tedy vypadá následovně:

with (objekt){
příkazy
}

Prakticky to má ten význam, že ve skriptu nemusíme rozepisovat označení objektu v objektové hierarchii. Námi již použitý ukázkový skript

/* Opet skript Hello World!
Tentokrat s vyuzitim promennych */
//Nejprve promenne myDocument priradime novy dokument
var myDocument=app.documents.add();
//pridame promennou myTextFrame obsahujici novy textovy ramecek
var myTextFrame=myDocument.textFrames.add();
//nastavime rozmery ramecku
myTextFrame.geometricBounds = ["0p0", "0p0", "18p0", "18p0"];
//a priradime text
myTextFrame.contents = "Hello World!";

lze s pomocí with zapsat takto

/* Opet skript Hello World!
Tentokrat s vyuzitim promennych a vyrazu with */
//Nejprve promenne myDocument priradime novy dokument
var myDocument=app.documents.add();
with(myDocument){
               //pridame promennou myTextFrame obsahujici novy textovy ramecek
               var myTextFrame=textFrames.add();
               with(myTextFrame){
                   //nastavime rozmery ramecku
                   geometricBounds = ["0p0", "0p0", "18p0", "18p0"];
                   //a priradime text
                   contents = "Hello World!";
                   }
}

Na první pohled může daný zápis vypadat jako obrovská pomůcka (ušetříme hodně psaní). Realita je ale taková, že použití with přispívá u delšího kódu s vícero vnořeními podle našich zkušeností spíše k zmatení čtenáře skriptu, navíc má použití toho výrazu různé vedlejší nechtěné efekty (včetně třeba zpomalení skriptu). Z uvedených důvodů se až na další budeme danému výrazu v našem tutoriálu vyhýbat, nechceme jej ale samozřejmě tímto našim čtenářům nějak jednoznačně zapovídat. (Do jisté míry se zde jedná spíše o subjektivní postoj, který nicméně sdílíme s některými renomovanými odborníky.)

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » VSE  

 » Rubriky  » Go verze  

 » Rubriky  » Sazba  

 » Rubriky  » Software  

Poslat článek

Nyní máte možnost poslat odkaz článku svým přátelům:

Váš e-mail:

(Není povinný)

E-mail adresáta:

Odkaz článku:

Vzkaz:

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: