V předchozím článku „Editace položek ve vícesloupcovém seznamu“ jsme si ukázali některé základní postupy obsluhy vícesloupcového seznamu a editace jeho položek. V tomto článku na uvedené navážeme a předvedeme si další funkci vícesloupcového seznamu: jeho třídění podle jednotlivých sloupců.

Zde je příklad, jak to celé funguje. Proti minulému příkladu přibyla nad jednotlivými sloupci tlačítka se šipkami, jejichž pomocí můžeme seznam třídit podle uvedeného sloupce vzestupně, potažmo sestupně:

Cena Typ Km/h
Cena:  
Typ:  
Km/h:  
   

Pro úsporu místa zde nebudeme uvádět kód celého příkladu - je ostatně podrobně popsán v předchozím článku - ale zaměříme se pouze na přidané funkce.

Nejprve tlačítka se šipkami. Do tabulky, obsahující jednotlivé prvky formuláře, jsme přidali jeden řádek, v jehož buňkách je uvedena vždy dvojice tlačítek, volajících příslušnou třídící funkci. Zde jsou HTML kódy pro tato tlačítka:

V prvním sloupci:
<input type="button" value=" v " name="sort" onClick="SortDown(this.form.field1,true)">
<input type="button" value=" ^ " name="sort" onClick="SortUp(this.form.field1,true)">
Ve druhém sloupci:
<input type="button" value=" v " name="sort" onClick="SortDown(this.form.field2,false)">
<input type="button" value=" ^ " name="sort" onClick="SortUp(this.form.field2,false)">
Ve třetím sloupci:
<input type="button" value=" v " name="sort" onClick="SortDown(this.form.field3,true)">
<input type="button" value=" ^ " name="sort" onClick="SortUp(this.form.field3,true)">

Každé tlačítko volá po stisku (událost onClick) JavaScript funkci SortDown, případně SortUp. Ta zajišťuje setřídění vícesloupcového seznamu podle toho sloupce, který byl předán jako první parametr funkce. Druhým parametrem je příznak, zda se má třídit numericky, tj. podle číselných hodnot (hodnota true), nebo abecedně (hodnota false).

Zde je kód první ze zmíněných funkcí, SortDown:

function SortDown(theSelect,numeric) {
    with(theSelect) {
    for (var j = 0; j<length; j++){
        for(var i=0; i<length-1; i++){
            if(numeric) {
                if((1*options[i].value)>(1*options[i+1].value))
                    Swap(i,form);
            } else {
                if(options[i].value>options[i+1].value)
                    Swap(i,form);
            }
        }
    }
    }
    if(theSelect.selectedIndex >=0 )
        Reselect(theSelect)
}

Třídění probíhá klasickým BubbleSortem (k tomu ještě neoptimalizovaným, což ale u malého objemu dat příliš nevadí). K záměně sousedních polí seznamu je použita funkce Swap(index,form), jejíž kód si ukážeme níže. Rozlišení, zda se jedná o numerické, nebo abecední třídění, probíhá podmínkou přibližně uprostřed kódu funkce. Numerické třídění si vynutíme tím, že porovnávané hodnoty prvků vynásobíme jedničkou - jejich hodnota se tím nezmění, dojde však ke změně typu příslušné části výrazu z řetězcového na číselný, což má za následek jiný druh porovnání. Pokud však v některém sloupci porovnáváme číselné hodnoty, měli bychom navíc při zápisu do seznamu (kód tlačítka "Zapsat" v minulému příkladu) provést kontrolu, eventuelně opravu vstupních hodnot z příslušných editačních polí.

V závěru funkce SortDown volá funkci Reselect (opět viz minulý příklad), jež zabezpečí aktualizaci hodnot v editačních polích.

Kód funkce SortUp je prakticky totožný, jediná změna je v záměně porovnávacího operátoru za opačný na dvou klíčových místech funkce. Obě funkce lze, přidáním dalšího parametru a podmínky, sloučit do jedné, univerzální.

function SortUp(theSelect,numeric) {
    with(theSelect) {
    for (var j = 0; j<length; j++){
        for(var i=0; i<length-1; i++){
            if(numeric) {
                if((1*options[i].value)<(1*options[i+1].value))
                    Swap(i,form);
            } else {
                if(options[i].value<options[i+1].value)
                    Swap(i,form);
            }
        }
    }
    }
    if(theSelect.selectedIndex >=0 )
        Reselect(theSelect)
}

Zbývá kód poslední funkce, Swap, která "prohodí" dvě sousední položky (určené hodnotou parametru index a index+1) ve všech seznamech formuláře:

function Swap( index, theForm ) {
var tmp="";
    for( var i=1; i<=3; i++ ) {
        theSelect=eval("theForm.field"+i);
        tmp = theSelect.options[index].value;
        theSelect.options[index].value = theSelect.options[index+1].value;
        theSelect.options[index+1].value = tmp;
        tmp = theSelect.options[index].text;
        theSelect.options[index].text = theSelect.options[index+1].text;
        theSelect.options[index+1].text = tmp;
    }
}

Při výměně předpokládáme, že všechny sloupce formuláře jsou pojmenovány field1fieldN, v tomto případě N=3 (viz řádek s konstrukcí eval(...) ). Dále zaměňujeme nejen hodnoty prvků (vlastnost value), ale i zobrazený nadpis (vlastnost text). Konečně, výměna hodnot se děje "textovým" způsobem - přepisujeme řetězce, bez dalšího rozlišení, zda se jedná o textový nebo numerický údaj. Vzhledem k tomu, že zde nedochází k žádnému porovnávání, můžeme si toto zjednodušení dovolit.

A to je vše k třídění. Podmínkou úplné funkčnosti příkladu je pochopitelně zachování všech funkcí, o nichž jsme hovořili v předchozím článku. V kódu těchto funkcí nedošlo k žádným změnám.

Poznámky na okraj

  • Jako další rozšíření by určitě bylo zajímavé napodobit funkci třídících hlaviček seznamů z prostředí MS Windows, kdy obě třídící tlačítka jsou sloučena do jednoho, prvním stiskem dojde k vzestupnému třídění, druhým k sestupnému.
  • Při práci s tímto příkladem jsem "objevil" jedno ne zcela korektní chování uvedené techniky, které není popsáno v minulém článku. Dochází k němu, pokud seznam obsahuje více položek, než je jeho velikost - když se tedy objeví po stranách seznamu posuvníky. Někdy může při obsluze dojít k tomu, že ačkoliv je ve všech seznamech vybrán stejný řádek, graficky to na stránce vypadá, že jsou vybrány řádky různé - jeden ze seznamů je posunut posuvníkem do jiné polohy. V současnosti bohužel neznám řešení tohoto problému, které by fungovalo univerzálně na všech obvyklých prohlížečích: definice JavaScriptu verze 1.2 neobsahuje metody ani vlastnosti ovládacího prvku SELECT, které by umožňovaly programově pohybovat posuvníky. Pro Internet Explorer by zřejmě bylo částečným řešením některé z obvyklých rozšíření standardu ala Microsoft. Pokud někdo znáte univerzální řešení, budu rád za příspěvek do diskuze.

Přeji vám příjemný den.

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

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

Žádný příspěvek v diskuzi

Odpovědět