Jak upravit vykreslení HTML kódu menu v Drupalu (aneb dvouřádkové menu)

V systému Drupal máte k dispozici mocné API a systém šablon, s nimiž dohromady můžete upravit základní vzhled a chování jednotlivých prvků webu. Například přetvořit běžné menu do víceřádkové podoby.

Jak vypadá standardní menu v redakčním systému Drupal asi všichni dobře víte. Z pohledu uživatele to je vždy co položka, to odkaz. Z pohledu zdrojového kódu HTML je menu tvořeno seznamem <ul>, s položkami <li>, ve kterých jsou odkazy <a>. Tyto odkazy vycházejí z toho, co napíšete do políčka Nadpis odkazu menu v administrační části Drupalu.

Mnohdy ale grafické zadání webu, které musíte v Drupalu zpracovat, předpokládá či vyžaduje trošku jinou HTML strukturu pro vygenerované menu. Typickým příkladem je situace, kdy potřebujete vložit nějaké pozadí nikoli do značky <li>, ale přímo pro značku <a>. Jenže co když grafika vyžaduje ještě další pozadí pro odkaz, který už ale nemáte kam přiřadit? Hodila by se vám v odkazu značka <span>, kterou ale Drupal standardně negeneruje?

Nebo trošku složitější příklad z praxe. Řekněme, že máte zadání, ve kterém je potřeba vytvořit dvouřádkové menu. Každá položka by měla vykreslit jak odkaz daný textem Nadpis odkazu menu, tak ještě nějakou vysvětlivku k tomuto odkazu. Z pohledu administrace žádný problém. Pro vysvětlivku pod odkazem můžete použít políčko Popis. Problém je v tom, že obsah tohoto pole Drupal renderuje coby atribut title značky <a>, tedy plovoucí nápovědu zobrazenou po ponechání myši nad odkazem. Jak jej donutit vypsat tento text přímo do značky <li>?

Drupal

Vše zařídí funkce v template.php

Pomocí souboru template.php můžete do tématu vzhledu implementovat některé funkce z Drupal API, mimo jiné zde můžete na úrovni tématu vzhledu nechat upravit renderování menu. Za předpokladu, že chceme upravit sestavování HTML pro odkazy hlavního menu (main menu), doplňte si do souboru template.php funkci function NAZEVVZHLEDU_menu_link__main_menu(array $variables){}.

Připomínám, že pokud soubor template.php ve svém tématu vzhledu nemáte, stačí jej prázdný vytvořit a na jeho začátek umístit <?php.

Pokud byste si nyní nechali s pomocí modulu Devel a funkce dsm() zobrazit obsah proměnné $variables, tedy dsm($variables);, zjistíte, že se tato funkce volá pro každou z položek menu a vždy je k dispozici pole $variables['element']. S ním budeme pracovat, protože jsou v něm uvedeny jednotlivé vlastnosti každé z položek menu.

Drupal

Základní podoba této funkce, která by nechala vytvořit hlavní menu Drupalu v nezměněné podobě, by vypadala takto:

{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; } function maxiorel3_menu_link__main_menu(array $variables) { $element = $variables['element']; $sub_menu = ''; if ($element['#below']) { $sub_menu = drupal_render($element['#below']); } $output = l($element['#title'], $element['#href'], $element['#localized_options']); return '
  • ' . $output . $sub_menu . "
  • \n"; } {/syntaxhighlighter}

    Všimněte si, že nejprve zjišťuje, zda má aktuálně zpracovávaná položka menu nějaké zanořené potomky. Pokud ano, pak pomocí drupal_render() nechá vykreslit toto podmenu (přičemž se pro jeho jednotlivé položky opět volá tato naše funkce samotná). Následně se pomocí funkce l() vytvoří odkaz pro danou položku menu a na výstupu z funkce se jak odkaz, tak případné podmenu vykreslí do značky <li>.

    Doplnění značky <span> do odkazu menu

    Pro případ, že bychom chtěli doplnit do každého odkazu HTML značku <span>, abychom pak mohli hlavní menu lépe nastylovat, stačí provést mírnou úpravu v části, kde se volá funkce l().

    {syntaxhighlighter brush: php;fontsize: 100; first-line: 1; } function maxiorel3_menu_link__main_menu(array $variables) { $element = $variables['element']; $sub_menu = ''; if ($element['#below']) { $sub_menu = drupal_render($element['#below']); } $element['#localized_options']['html'] = true; $output = l(''.$element['#title'].'', $element['#href'], $element['#localized_options']); return '
  • ' . $output . $sub_menu . "
  • \n"; } {/syntaxhighlighter}

    Nejprve do pole, ve kterém se předávají vlastnosti odkazu pro vytvoření funkcí l() přidáme informace, že odkaz bude obsahovat HTML, tedy že uvnitř budoucí značky <a> nebude jen prostý text. Funkce l() očekává jako první parametr obsah budoucí značky <a>, takže původní text menu dostupný v $element['#title'] obalíme dvojicí řetězců se <span> a </span> a jsme hotovi.

    Tip: Podobný postup s úpravou HTML obsahu odkazu menu lze využít třeba v případě, kdy chcete vytvořit obrázkové menu bez textů. Vytvoříte si podmínku porovnávající, zda je v $element['#title'] odpovídající text menu a místo něj necháte do funkce l() vykreslit značku <img> s adresou konkrétního obrázku.

    Vytvoření dvouřádkového menu

    Jinou zajímavou úpravou, na kterou využijete zpracování položek hlavního menu pomocí template.php, je vytvoření zmíněného dvouřádkového menu. V praxi jej lze vidět třeba na webu www.bcas.cz.

    V podstatě potřebujeme zjistit, v jaké části pole obsahujícího informace o položce menu je k dispozici obsah vyplněný v administraci jako Popis. Pokud byste prozkoumali obsah pole $element (resp. $variables['element']), zjistíte, že jej máte k dispozici v $element['#original_link']['options']['attributes']['title']. Pak už stačí jen poskládat text pro funkci l(), podobně jako jsme to dělali výše při doplňování spanu.

    V tomto případě ale ještě ověříme, zda se vykresluje položka první úrovně nebo položka podmenu. V první úrovni dvouřádkový text nechceme a ponecháme jen základní podobu menu. Jestliže ale $element['#original_link']['plid'], tedy číslo nadřazené položky obsahuje nějakou kladnou hodnotu, pak se nám jedná o odkaz v podmenu a můžeme dvojitý text vykreslit.

    Ve výsledné ukázce tedy vidíte toto ověření a vytvoření položky podmenu tak, aby v odkazu byl nejprve ve značkách <strong></strong> umístěn původní text menu, následuje zalomení a ve značkách <em></em> text popisu menu.

    {syntaxhighlighter brush: php;fontsize: 100; first-line: 1; } function maxiorel3_menu_link__main_menu(array $variables) { $element = $variables['element']; $sub_menu = ''; if ($element['#below']) { $sub_menu = drupal_render($element['#below']); } if ($element['#original_link']['plid'] != 0 && isset($element['#original_link']['options']['attributes']['title'])){ $element['#localized_options']['html'] = true; $output = l(''.$element['#title'].'
    '.$element['#original_link']['options']['attributes']['title'].'', $element['#href'], $element['#localized_options']); } else{ $output = l($element['#title'], $element['#href'], $element['#localized_options']); } return '
  • ' . $output . $sub_menu . "
  • \n"; } {/syntaxhighlighter}

    Nastíněné možnosti úprav vám dávají plnou kontrolu nad tím, jak se výsledné hlavní menu v Drupalu vykreslí a máte tak možnost jej upravit přesně podle potřeb grafického návrhu. Jakmile docílíte požadované HTML struktury bude samozřejmě následovat práce s CSS, což je ale rutina.

    Pro méně zkušené připomínám též článek Jak na rozbalovací menu jen s CSS a bez doplňkových modulů v Drupalu.

    Tagy

    Buďme ve spojení, přihlaste se k newsletteru

    Odesláním formuláře souhlasíte s podmínkami zpracováním osobních údajů. 
    Více informací v Ochrana osobních údajů.

    Autor článku: Jan Polzer

    Tvůrce webů z Brna se specializací na Drupal, WordPress a Symfony. Acquia Certified Developer & Site Builder. Autor několika knih o Drupalu.
    Marketing Director v Lesensky.cz. Ve volných chvílích podnikám výlety na souši i po vodě. Více se dozvíte na polzer.cz a mém LinkedIn profilu.

    Komentáře k článku

    Přidat komentář

    Odesláním komentáře souhlasíte s podmínkami Ochrany osobních údajů

    reklama
    Moje kniha o CMS Drupal

     

    Kniha 333 tipů a triků pro Drupal 9


    Více na KnihyPolzer.cz

    Sledujte Maxiorla na Facebooku

    Maxiorel na Facebooku

    Poslední komentáře
    Hosting pro Drupal a WordPress

    Hledáte český webhosting vhodný nejenom pro redakční systém Drupal? Tak vyzkoušejte Webhosting C4 za 1200 Kč na rok s doménou v ceně, 20 GB prostoru a automatické navyšováním o 2 GB každý rok. Podrobnosti zde.

    @maxiorel na Twitteru

    Maxiorel na Twitteru