JQuery knihovna pro tvorbu layoutu webových aplikací

Před časem jsem pro svůj redakční systém hledal javascriptové udělátko pro tvorbu layoutu. Jako obvykle mi žádné z dostupných řešení nevyhovovalo, tak jsem si ho napsal sám a nyní jej uvolňuji jako opensource.

Ono vlastně „nyní“ je trochu silné slovo. Je to už pár let staré řešení. Před víc než půl rokem jsem jej mírně upravil pro aktuální verzi jQuery, očistil s tím, že jej uvolním jako opensource. Založil jsem na to projekt na http://code.google.com/p/moonjs/, vzápětí jsem na to zapomněl a nikomu o tom neřekl :). Dneska jsem si na to vzpomněl, tak o tom aspoň napíšu sem.

Takže o co jde: je to něco jako layoutovací modul z ExtJS, jenže mnohem jednodušší. Oproti ExtJS je to jednoduchoučká jednoúčelová nevtíravá knihovnička, která je psána tak, aby co nejméně ovlivňovala okolí. Ostatně podívejte se na demo a uvidíte sami.

Jak to funguje

Základem layoutu je hierarchický (binární) strom panelů. Každý panel může (ale nemusí) být rozdělen na dvě části, a to buď horizontálně nebo vertikálně. Každá z těchto částí může být zase rozdělená a tak dál až donekonečna. Chování panelů lze ovlinit několika parametry, které popíšu dále.

Zajímavou vlastností (kterou jsem u podobných řešení postrádal) je možnost kombinování šířek (výšek) panelů zadaných v pixelech a v procentech. Pokud má panel šířku zadanou v procentech, pak se při změně velikosti okna prohlížeče (nebo změně velikosti nadřazeného panelu) přepočítá skutečná šířka panelu tak, aby procenta seděla. Pokud má však šířku zadanou v pixelech, zůstává zadaná šířka přesně zachována.

Ačkoliv jsem využil knihovnu jQuery, není řešení implementováno jako jQuery plugin, ale jako klasické javascriptové konstruktory („třídy“ chcete-li) ve vlastním jmenném prostoru (moon). Považuju to za flexibilnější.

K dispozici jsou následující dva konstruktory moon.Panel a moon.PanelSplit. Způsob použití je nejlépe patrný z dema:

$(document).ready(function()
{
    // Vytvoření instance panelu:
    var panelMain = new moon.PanelSplit({
        axis: 'y',
        position: ' 10px',
        resizable: false,        
        showHandler: false,         
        firstPanel: {
            type: 'Panel',            
            sizing: 'contentHeight',             
            content: $("#header")       
        },        
        secondPanel: {            
            type: 'PanelSplit',            
            axis: 'y',              
            position: '60px',             
            masterPane: 'second',             
            handlerWidth: 15,            
            firstPanel: { … },             
            secondPanel: {                  
                type: 'Panel',                  
                content: $("#footer")          
            }        
        }  
    });
    
    // Panel připojím do dokumentu
    panelMain.outer.appendTo($('body'));    
    
    // Při resizování okna prohlížeče je nutno překreslit layout 
    $(window).bind('resize', function(){
        panelMain.redraw();
    });
    
    // Při načtení dokumentu zavoláme počáteční překreslení layoutu
    panelMain.redraw();
}

Každý konstruktor panelu má jako parametr konfigurační objekt, jehož vlastnosti ovlivňují chování a zobrazení panelu a handleru. Vlastnost type určuje typ panelu (nyní 'Panel' nebo 'PanelSplit'). Je to taková obezlička, aby se dal použít konfigurační objekt uložit jako JSON a nefigurovala v něm volání konstruktorů panelů. Možnosti konfigurace jsou následující:

Panel
type 'Panel' Následující volby platí pro jednoduchý panel.
content string | jQuery Obsah panelu. Může být řetězec nebo jQuery objekt.
sizing 'fit' | 'contentWidth' | 'contentHeight' | 'contentBoth' Způsob určování rozměru panelu. Výchozí je 'fit', což znamená, že panel se přizpůsobí rozměrům nadřazeného panelu. Ostatní volby jsou spíš experimentální – panel se 'jakoby' vyrenderuje bez omezení a pro jeho rozměry se použije šířka, výška, nebo oba rozměry takto vyrenderovaného obsahu. Pokud se to překombinuje, můžou nastat nepředvídatelné konfliktní situace.
PanelSplit
type 'PanelSplit' Následující volby platí pro rozdělený panel.
axis 'x' | 'y' Určuje osu rozdělení panelu, 'x' znamená vertikální rozdělení, 'y' horizontální.
position 'Npx' | 'N%' Pozice handleru, neboli šířka (výška) panelu. Může být zadaná v pixelech nebo v procentech - podle toho se mění chování panelu při změně velikosti. To, kterému panelu šířku (výšku) zadáváme (zda prvnímu nebo druhému) se určuje parametrem 'masterPane'.
masterPane 'first' | 'second' Určuje "hlavní" panel, neboli panel, kterému zadáváme počáteční šířku (výšku). Šířka (výška) druhého panelu se dopočítá automaticky jako doplněk do celkové zbylé šířky (výšky).
resizable true | false Zda je možné měnit velikost panelu myší táhnutím za handler.
handlerWidth
int Šířka handleru v pixelech. Výchozí hodnota je 7 pixelů.
showHandler true | false Zda zobrazit handler či nikoliv.
firstPanel
Konfigurační objekt (popř. přímo instance) prvního panelu (první = levý nebo horní). Jde o instanci objektu typu moon.Panel nebo moon.PanelSplit.
secondPanel
Konfigurační objekt (popř. přímo instance) druhého panelu (druhý = pravý nebo spodní). Jde o instanci objektu typu moon.Panel nebo moon.PanelSplit.

Stylování panelů je 100% řízeno CSS třídami (viz CSS soubor, který je přilinkován k demu).

A to je vše. Nejedná se o nijak robustní řešení, naopak – hlavním cílem byla co nejjednodušší implementace. Jistě by se našla spousta vlastností, které by se hodily, např. perzistence stavu panelů apod. Na druhou stranu to v této podobě už nějakou dobu používám a celkem mi to vyhovuje. Funkčnost testována ve většině současných prohlížečů, od IE6 výš včetně. Licence MIT. Třeba se to někdy někomu bude hodit.

Datum: 1. 12. 2009, Autor: Karel Fučík

Komentáře (1)

  • 1
    Martin Michálek (web) 2. 12. 2009, 0.49
    Hezké, napadlo mě hned jedno použití. Doufám, že se k němu brzy dostanu. Díky!

Přidat komentář

(nebude zveřejněn)

Ochrana proti spamu (prosím, zodpovězte následující otázku):

Položky označené * jsou povinné. 1 enter = nový řádek. Žádná syntaxe typu Texy není rozpoznávána, HTML bude escapováno.

Nejnovější komentáře