Maxlength a progressbar v poli textarea pomocí JavaScriptu

11. ledna 2005

Formulářové pole textarea umožňuje vkládat i velmi dlouhé texty, jehož maximální délku narozdíl od textového pole není jednoduše možné omezit, protože atribut maxlength zde není podporován. V tomto příkladu si ukážeme, jak pomocí klientského skriptu nejen omezit maximální délku, ale i zvýšit komfort uživatele zobrazením poměrného využití povolené délky grafickým progressbarem.

Předem je potřeba říci, že uvedený příklad využívá JavaScript pro náhradu chybějící podpory maxlength a pracuje tedy na klientské straně – i když jej použijeme pro omezení maximální délky zadávaného textu, je vždy nutností ošetřit maximální délku také na serveru, kde formulář zpracováváme. Pokud má klient JavaScript vypnutý nebo jej nepodporuje, naše kontrola bude zcela neúčinná.

Princip našeho skriptu je vcelku jednoduchý – budeme reagovat na události v poli textarea a při každém vyvolání události ověříme délku zadaného textu. Pokud je text delší než maximální povolená délka, zobrazíme hlášení a text prostě ořízneme na povolenou délku. Z délky zadaného textu a maximální povolené délky stanovíme délku progressbaru pro vykreslení. Chytře je zde využita vlastnost offsetWidth, díky které automaticky nastavíme celkovou délku progressbaru shodnou s aktuální šířkou textového pole, progressbar bude tedy vypadat dobře ve většině prohlížečů nezávisle na tom, jak daný prohlížeč interpretuje zobrazení pole textarea. Vyzkoušejte si ukázku (zdrojový kód).

Příklad formuláře s polem textarea:

<form action=““ method=“POST“>
  <fieldset>
    <legend><span style=“text-decoration:underline;“>T</span>ext zprávy</legend>
    <div>
      <textarea name=“TextArea“ id=“TextArea“ accesskey=“T“ rows=“6″ cols=“50″ wrap=“virtual“
        onpropertychange=“MaxLengthCount(this,160);“
        onclick=“MaxLengthCount(this,160);“
        onmousemove=“MaxLengthCount(this,160);“
        onblur=“MaxLengthCount(this,160);“
        onkeyup=“MaxLengthCount(this,160);“
        onfocus=“MaxLengthCount(this,160);“
        onchange=“MaxLengthCount(this,160);“
        onafterupdate=“MaxLengthCount(this,160);“></textarea>
      <div id=“TextArea_PBar“ style=“width:0px;height:10px;border:0;font-size:8px;overflow:hidden;background-color: #3399FF;“></div>
    </div>
    <input type=“button“ value=“Odeslat“ />
  </fieldset>
</form>

V poli textarea obsluhujeme události, které nastávají při práci uživatele s tímto polem – princip je analogický jako při zobrazování počtu napsaných znaků ve vlastním ICQ Pageru nebo hlídání povoleného formátu. Reagujeme na události onclick, onmousemove, onblur, onkeyup, onfocus, onchange, onafterupdate, onpropertychange, přičemž poslední dvě jsou proprietární události prohlížeče Microsoft Internet Explorer. Poskytují vyšší komfort uživateli (například při delším přidržení jedné klávesy je délka textu přepočítávána okamžitě, nečeká se na uvolnění klávesy – onkeyup), fungují však pouze v MSIE a ačkoli v ostatních moderních prohlížečích nezpůsobí chybu, je potřeba je odebrat, pokud požadujeme striktně validní dokument.

Obsluhu události zajišťuje funkce MaxLengthCount, které předáváme odkaz na objekt vyvolávající událost a maximální povolenou délku textu:

var MaxLengthLock = false;
function MaxLengthCount(fieldObj,fieldMaxLength)
{
  if (!MaxLengthLock)
  {
    MaxLengthLock = true;
    if (fieldObj.value.length > fieldMaxLength)
    {
      alert(„Text je delší než “ + fieldMaxLength + “ znaků!“);
      fieldObj.value = fieldObj.value.substring(0,fieldMaxLength);
    }
    var percentage = parseInt(100 – (( fieldMaxLength – fieldObj.value.length) * 100)/fieldMaxLength);
    document.getElementById(fieldObj.id + „_PBar“).style.width = parseInt((parseInt(fieldObj.offsetWidth)*percentage)/100)+“px“;
    MaxLengthLock = false;
  }
}

Součástí skriptu je pomocná proměnná MaxLengthLock, která nám pomáhá zajistit, aby funkce pro přepočítávání délky textu byla takzvaně reentrantní, čili aby mohla být souběžně spuštěná vícenásobně. K takovému vícenásobnému spuštění může lehce dojít, protože reagujeme na více událostí a některé skutečně mohou nastat současně nebo těsně po sobě – v takovém případě by se nám souběžně běžící výpočet ve funkci mohl „potlouci“, a tak jednoduše umožníme pouze jedno zpracování. Díky této logické proměnné hned na začátku funkce rozlišíme, zda právě neprobíhá výpočet v závislosti na jiné předchozí události, a pokud ano, žádný výpočet nebudeme provádět. Pokud výpočet neprobíhá, hned na začátku výpočtu nastavíme MaxLengthLock na true (ostatní požadavky na výpočet tak budou ignorovány), po ukončení výpočtu (na konci obslužné funkce) musíme MaxLengthLock nastavit opět na false, abychom tak „odemkli“ provedení výpočtu pro příští obsluhu události.

Při výpočtu nejprve ověříme, zda aktuální délka textu není delší než zadaná povolená délka – pokud ano, zobrazíme chybové hlášení a aktuální text pomocí metody substring() ořízneme na povolenou délku. Dále si stanovíme, na kolik procent je již textové pole zaplněno (uložíme do proměnné percentage.) Zbývá jen dané procentuální zaplnění přepočítat na skutečnou délku progressbaru. Ta je, jak jsem již zmínil, odvozena od aktuální šířky textového pole prostřednictvím vlastnosti offsetWidth.

Jak vidíme z ukázky, id elementu tvořícího progressbar vychází z id textového pole s přidaným řetězcem „_PBar“. Jednoduše tak můžeme použít metodu getElementById() pro získání přístupu k objektu progressbaru. Uvedený způsob umožní mít ve stránce několik textových polí s vlastním progressbarem aniž bychom museli obslužnou funkci zvlášť přepisovat.

Nakonec nastavíme vlastnost style.width objektu progressbaru na přepočítanou hodnotu a progressbar patřičné délky se vykreslí.

Pro skutečné použití by se hodilo nahradit v ukázce použité inline styly (definované v atributech style) externím souborem. Omezení textu v poli textarea se určitě hodí všude tam, kde je délka povoleného textu omezená, například u SMS brány nebo Messengeru.

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 *