Výtahy z textu na stránce pomocí JavaScriptu a CSS

6. října 2004

Z novin a časopisů možná výtahy z textu znáte. Jedná se o části článků, vykreslené větším písmem a obvykle ohraničené rámečkem, kde se nachází nějaký zajímavý úryvek z textu – úkolem těchto výtahů je čtenáře zaujmout natolik, aby si článek přečetl. Na webu je vytvoření podobných výtahů trochu složitější, protože se nemůžeme plně spoléhat na vizuální podobu stránky, ale i přesto to jde…

Pokud ještě nevíte, co to výtahy jsou, podívejte se na názornou ukázku.

Jak na to nejjednodušeji

Nejjednodušším způsobem, jak podobné výtahy vytvořit, by bylo vložit do textu stránky odstavec s výtahem…

<p class=“vytah“>Text výtahu…</p>

…a přiřadit příslušné zobrazení:

p.vytah {
  font-size: 120%;
  font-weight: bold;
  font-family: serif;
  float: left;
  width: 200px;
  w\idth: 170px;
  border-top: 3px solid black;
  border-bottom: 1px solid black;
  padding: 5px 10px;
  margin: 10px 10px 10px 0;
}

Toto řešení ale není správné z jednoho důvodu – pokud stránka bude prohlížena bez stylů, nebude článek dávat smysl, protože výtah je tvořen textem, který se vyskytuje na jiném místě tohoto článku. Bez stylů tedy bude takový odstavec naprosto bez kontextu, bude opakovat něco, co se říká na jiném místě článku, a čtenáře více než co jiného spíše zmate.

Lepší řešení

Lepší by bylo pouze označovat části textu článku, ze kterých se mají vytvořit výtahy, a místa, kam se mají výtahy umístit, o vše ostatní by se již postaral JavaScript. Zkontroloval by podporu CSS v prohlížeči (prohlížeče bez podpory CSS ale většinou nepodporují ani JavaScript, takže už jeho použití pro vytvoření výtahů pravděpodobně nevhodné prohlížeče vyřadí ze hry) a příslušné části textu by zkopíroval na určená místa, kde by se z nich vytvořily pomocí CSS výtahy. Shodou okolností jsem takový skript napsal a teď vám ukážu, jak s ním pracovat.

Příprava (X)HTML kódu

Části textu budeme označovat pomocí prvku <span class="vypichnout">:

<p>Libě řikohří úfůchou křať o subreši bas zuša ktopěsu. <span class=“vypichnout“>1 Siř hrůlvi v prudrá hec věrouh o opé lachre trazavě rycali.</span> Děca věhuj z věktýhuž.</p>

Uvnitř se mohou nacházet i různé další prvky, například <strong> nebo <em>, skript je do výtahu také přenese (můžete jim ale samozřejmě zrušit jejich typické zobrazení pomocí CSS).

Části textu, kam se budou výtahy umísťovat, budeme označovat pomocí prvku <span class="umistit-vytah">:

<p>Hryč lek kemašt soň stoudryrév lij přašt zecouď zudřomédre a zýšt.<span class=“umistit-vytah“></span> Usiž k hrémikté zacho řouh a luzyh duze juj buz lazož.</p>

Odstavce jsem si k umísťování výtahu nevybral, protože jsem chtěl dosáhnout efektu, kde výtah zasahuje částečně do dvou, případně více odstavců, a to jde jenom pomocí plovoucího řádkového prvku uprostřed textu, proto tedy ten <span>.

Prvky <span class="vypichnout"> a <span class="umistit-vytah"> se samozřejmě mohou vyskytovat i jinde než jen v odstavcích.

Zobrazení v CSS

Výtahy budou mít přiřazenu třídu vytah, je proto také dobré připravit si pro ně v CSS určité zobrazení. Já jsem použil následující:

span.vytah {
  font-size: 120%;
  font-weight: bold;
  font-family: serif;
  float: left;
  width: 200px;
  w\idth: 170px;
  border-top: 3px solid black;
  border-bottom: 1px solid black;
  padding: 5px 10px;
  margin: 10px 10px 10px 0;
}

Toto řešení počítá s tím, že výtahy budou plavat pomocí vlastnosti „float“. Ostatní zobrazení záleží už ale jenom na vás, dobrým nápadem může být třeba přidání nějaké grafiky na pozadí.

Generovaný kód

Na jedné stránce můžete označit libovolné množství textů k výtahu (samozřejmě i žádný), ale jejich počet se musí shodovat s počtem prvků <span class="umistit-vytah">. Skript poté přiřadí první označený text k prvnímu prvku <span class="umistit-vytah">, druhý k druhému a tak dále.

Po proběhnutí skriptu (po nahrání stránky) se vytvoří takovýto kód:

<p>Hryč lek kemašt soň stoudryrév lij přašt zecouď zudřomédre a zýšt.<span class=“umistit-vytah“><span class=“vytah“>(text označený k výtahu)</span></span> Usiž k hrémikté zacho řouh a luzyh duze juj buz lazož.</p>

Kopírování atributů

Skript zároveň kopíruje i všechny atributy prvku <span class="vypichnout">, takže můžete vybraný text jednoduše nechat třeba odplavat doprava:

<p>Libě řikohří úfůchou křať o subreši bas zuša ktopěsu. <span class=“vypichnout vpravo“>1 Siř hrůlvi v prudrá hec věrouh o opé lachre trazavě rycali.</span> Děca věhuj z věktýhuž.</p>

Z tohoto kódu vznikne takovýto výtah:

<p>Hryč lek kemašt soň stoudryrév lij přašt zecouď zudřomédre a zýšt.<span class=“umistit-vytah“><span class=“vpravo vytah“>1 Siř hrůlvi v prudrá hec věrouh o opé lachre trazavě rycali.</span></span> Usiž k hrémikté zacho řouh a luzyh duze juj buz lazož.</p>

Teoreticky by pak mělo stačit vytvořit v CSS zobrazení pro selektor span.vpravo, ale takové pravidlo by se použilo i pro prvek <span class="vypichnout vpravo">. Proto by bylo nejlepší použít vícenásobnou třídu span.vytah.vpravo, ale takové selektory interpretuje špatně Microsoft Internet Explorer (MSIE). Proto podmíníme použití pravidla tím, aby se prvek nacházel v prvku <span class="umistit-vytah">. Stejným způsobem byste měli určovat zobrazení i pro jiné přídavné třídy výtahů.

span.umistit-vytah span.vpravo {
  float: right;
  margin: 10px 0 10px 10px;
}

Podobným způsobem jako třída se pro prvek <span class="vytah"> zkopíruje i atribut „id“, přičemž u prvku <span class="vypichnout"> se zároveň zruší (protože na jedné stránce nesmí být dva stejně pojmenované prvky). Pokud budete chtít v závislosti na tomto atributu přiřadit prvku nějaké zobrazení v CSS, musíte použít stejný postup jako u tříd (tedy selektor span.umistit-vytah span#id-prvku) – jinak by toto zobrazení bylo použito až do spuštění skriptu (tedy do úplného nahrání stránky) pro prvek <span class="vypichnout">.

Stáhnutí a připojení skriptu ke stránce

Skript byl i s CSS bez problémů testován na MSIE 5, MSIE 5.5, MSIE 6, Mozille a Opeře 7. O jeho použití teď již víte vše potřebné, stačí vám jenom si stáhnout soubor s tímto skriptem a připojit ho ke své stránce:

<script type=“text/javascript“ src=“vytahy.js“ defer=“defer“></script>

Zbytek článku se bude věnovat popisování skriptu, který zajistí vytvoření výtahů. Pokud vás tento skript nezajímá a stačí vám vědět, jak ho používat, můžete čtení článku ukončit. Pokud ale chcete vědět, jak tento skript funguje (a případně si ho i upravit) a trochu si zopakovat DOM, čtěte dál.

Skript pro vytvoření výtahů

Výše odkazovaný soubor se skriptem obsahuje jenom nutné minimum komentářů a není ani příliš přehledný, protože mi šlo o minimální velikost souboru. Daleko lépe je na tom skript v již odkazované ukázce výtahů. I tak si k němu ale nyní něco řekneme.

Vytvoření výtahu zajistí funkce vytvoritVytahy():

function vytvoritVytahy()
{

Na začátku deklarujeme několik proměnných a poté testujeme schopnosti prohlížeče:

  var vsechnyPrvky, vytahy = new Array(), umisteniVytahu = new Array(), i;
  vsechnyPrvky = (document.all ? document.all : (document.getElementsByTagName ? document.getElementsByTagName(„*“) : null));
  if (!document.getElementById || !vsechnyPrvky) return false;
  if (!(document.styleSheets || document.implementation.hasFeature(„StyleSheets“,““) || document.implementation.hasFeature(„CSS“,““) || document.implementation.hasFeature(„CSS2″,““))) return false;

Nejprve se do proměnné vsechnyPrvky přiřadí pole všech prvků v dokumentu (v MSIE pomocí document.all, v ostatních prohlížečích pomocí document.getElementsByTagName("*")). Pokud prohlížeč nedokáže toto pole vytvořit nebo pokud nepodporuje metodu document.getElementById(), je funkce ukončena. Dále testujeme podporu CSS – prohlížeč musí vykazovat podporu alespoň u jednoho ze čtyř uvedených způsobů testování.

V dalším kroku procházíme pole všech prvků a hledáme prvky obsahující text k výtahu:

  for (i = 0; i < vsechnyPrvky.length; i++) {
    if (vsechnyPrvky[i].tagName.toLowerCase() == „span“ && vsechnyPrvky[i].className.search(/(^v| v)ypichnou(t$|t )/) != -1) {
      vytahy[vytahy.length] = vsechnyPrvky[i].cloneNode(true);
      vsechnyPrvky[i].removeAttribute(„id“);
    }
  }

Pokud právě procházený prvek <span> obsahuje třídu „vypichnout“, nakopírujeme ho pomocí metody cloneNode() i s jeho následovníky (díky tomu, že metodě předáváme „true“) do pole výtahů a u původního prvku odstraníme atribut „id“.

Zajímavý je regulární výraz k detekci třídy. Určuje, že před a za textem „vypichnout“ v atributu „class“ může být jen mezera nebo začátek či konec řetězce. To proto, aby detekci nevyhověla také například třída „vypichnout-neco“. (Přímé porovnání hodnoty atributu „class“ s řetězcem „vypichnout“ jsme nemohli provést, protože zde může být obsaženo více tříd.)

Podobným způsobem vyhledáme i prvky, kam se mají výtahy umístit. Jediný rozdíl je v tom, že tentokrát si pouze ukládáme odkazy na tyto prvky.

  for (i = 0; i < vsechnyPrvky.length; i++) {
    if (vsechnyPrvky[i].tagName.toLowerCase() == „span“ && vsechnyPrvky[i].className.search(/(^u| u)mistit-vyta(h$|h )/) != -1) umisteniVytahu[umisteniVytahu.length] = vsechnyPrvky[i];
  }

Dále zkontrolujeme, jestli máme stejný počet výtahů jako prvků k umístění výtahu – pokud ne, skončíme:

if (vytahy.length != umisteniVytahu.length) return false;

V závěru funkce umístíme výtahy do příslušných prvků:

  for (i = 0; i < vytahy.length; i++) {
    vytahy[i].className = vytahy[i].className.replace(/(^v| v)ypichnou(t$|t )/, “ „);
    vytahy[i].className += “ vytah“;
    vytahy[i].className = vytahy[i].className.replace(/^ +/g, „“);
    umisteniVytahu[i].appendChild(vytahy[i]);
  }
  return true;
}

U každého výtahu odstraníme třídu „vypichnout“ (byla sem zkopírována z prvku <span class="vypichnout">), přidáme třídu „vytah“ a odstraníme mezery ze začátku atributu „class“ (ty se sem mohly dostat nahrazováním), které vadí Opeře 7. Poté již jen přidáme výtah do příslušného prvku pomocí metody appendChild().

Zbývá funkci vytvoritVytahy() ještě nějak zaregistrovat, aby se spustila po nahrání stránky. To by se dalo udělat zápisem window.onload = vytvoritVytahy;, ale ten má tu nevýhodu, že se takto dá zaregistrovat jen jedna funkce, a pokud tento zápis použijeme pro jinou funkci, přepíše se původní hodnota. Proto je lepší použít metodu DOM addEventListener(), respektive v MSIE její alternativu attachEvent(). Obě tyto metody umožňují registrovat libovolné množství funkcí pro spuštění po nahrání stránky. Já jsem si pro tento účel vytvořil následující funkci:

function regInitFcn (fcn)
{
  if (!window.addEventListener && !window.attachEvent) return false;
  if (window.addEventListener) window.addEventListener(„load“, fcn, false);
  else window.attachEvent(„onload“, fcn);
  return true;
}

Tato funkce zjistí, jakou metodu prohlížeč podporuje, a použije ji k zaregistrování funkce fcn pro spuštění po nahrání stránky. Naši funkci pro vytvoření výtahů pak zaregistrujeme takto:

regInitFcn(vytvoritVytahy);

Pokud budeme chtít zaregistrovat další funkce pro spuštění po nahrání stránky, stačí použít ten samý zápis:

regInitFcn(franta);
regInitFcn(pepa);
regInitFcn(marie);

Máme přitom jistotu, že budou spuštěny všechny zaregistrované funkce. Při použití window.onload se ale hodnota neustále přepisuje, proto by v následujícím případě byla spuštěna jen funkce marie():

window.onload = franta;
window.onload = pepa;
window.onload = marie;

A to je k výtahům všechno. Doufám, že se alespoň někteří z vás rozhodnou použít výtahy i na svém webu a text na českém internetu tak bude opět o něco čitelnější.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *