Vlastní vzhled

Drupal 8

Odvozené téma:

base theme: false
base theme: stable
base theme: classy

Externí odkazy v libraries.yml:

example:
  css:
    theme:
      # External URL.
      'http://example.com/test.css':
        type: external
      # Absolute path.
      /tmp/test.css: {}
      # Protocol free.
      //cdn.com/test.css: {}
      # Stream wrapper URI.
      'public://test.css': {}
      'example://test2.css': {}

Tipy:

Drupal 7

Při vytváření vlastního vzhledu je vhodné vycházet z některého ze základních témat vzhledu, které jsou uloženy v adresáři themes a z příručky Theme Guide (en). Pro výuku jsou také vhodná témata Zen (nejepší dokumentace) a Basic (jednoduché).

  1. V sites/all/themes vytvořte adresář vlastního vzhledu např. my_own_theme.
    • název adresáře (tématu) nesmí kolidovat s názvy modulů a nesmí začínat číslem
  2. V adresáři vlastního vzhledu vytvořte vhodnou adresářovou strukturu např.:
    • color
    • design
    • fonts
    • scripts
    • translations
  3. Adresář vlastního vzhledu může obsahovat soubory:
    • my_own_theme.info (vyžadovaný)
      • od Drupalu 7 není pomlčka (-) v názvu .info souboru akceptována (téma není přístupné v administraci) 
    • styles.css - použije se pro všechna média
    • logo.png
    • screenshot.png – náhled vzhledu
    • page.tpl.php
    • box.tpl.php – obal komentářů
    • comment.tpl.php
    • template.php
    • maintenance-page.tpl.php
    • fckstyles.xml – úprava výchozího nastavení stylů (elementů a atributů) modulu fckeditor
    • node.tpl.php – výchozí zobrazení všech typů obsahů
    • node-xxx.tpl.php – upřesnění zobrazení konkrétního typu obsahu (book, image, page, story, blog atd.)
    • comment-xxx.tpl.php – upřesnění zobrazení komentáře u konkrétního typu obsahu (book, image, page, story, blog atd.)
    • block-xxx.tpl.php – upřesnění zobrazení bloku (region, module atd.)
    • page-xxx.tpl.php – upřesnění zobrazení stránky (front, node, node-edit atd.)
    • block.tpl.php – zobrazení bloků
    • ...

 

.info

Konfigurační soubor .info (en) obsahuje základní informace a je vyžadován u každého tématu vzhledu. Název souboru musí být shodný s názvem adresáře.

Soubor musí obsahovat klíče:

name = Moje vlastní téma vzhledu
core = 6.x

Příklad:

name = Moje vlastní téma vzhledu
description = Popis tématu<br /><a href="http://tomas.dankovi.info/">Tomáš Daněk</a>
core = 6.x
engine = phptemplate
stylesheets[all][] = styles/all.css
stylesheets[screen, projection][] = styles/layout.css
stylesheets[screen, projection][] = styles/decoration.css
stylesheets[screen, projection][] = styles/modules.css
stylesheets[screen, projection][] = styles/fckeditor.css
stylesheets[print][] = styles/print.css

Další regiony viz regions.


Empty square brackets between the "[media]" and "= styleName.css" are always empty and denote that each stylesheet is appended to an array, as in php. Viz Adding style sheets.

html.tpl.php

Soubor modules/system/html.tpl.php obsahuje základní HTML strukturu stránky.

page.tpl.php

Soubor modules/system/page.tpl.php obsahuje šablonu stránky.

Promměnné souboru page.tp.php
Drupal 5 Drupal 6 Poznámky
Globální proměnné
  $base_path Adresa instalace Drupalu (vetšinou /)
  $css Pole CSS souborů aktuální stránky
  $directory Adresář aktuálního tématu vzhledu
  $is_front TRUE pokud je aktuální stránka úvodní stránkou (používá se společně s $mission)
  $logged_in TRUE pokud je uživatel přihlášen
  $is_admin TRUE pokud má uživatel oprávnění přístupu k administrační stránce
Metadata stránky
$language $language->language Textová reprezentace jazyka (en, cs...)
$language->dir Směr textu (ltr, rtl)
  $head_title Modifikovaná verze názvu stránky pro použití v elementu <title>
  $head Metadata, klíčová slova atd.
  $styles Připojení všech CSS stylů stránky (moduly, téma vzhledu atd.)
  $scripts Načtení JavaScript souborů a nastavení stránky

$body_classes Aktuální CSS třídy stránky: front / not-front,  logged-in / not-logged-in, page-... (node, admin, user...), node-type-... (page, story...), two-sidebars / one-sidebar sidebar-left / one-sidebar sidebar-right / no-sidebars
Identita stránky
$base_path $front_page Adresa úvodní stránky
  $logo Cesta k logu webu
  $site_name Název webu (zobrazení je možné povolit / zakázat v nastavení tématu vzhledu)
  $site_slogan Slogan webu (zobrazení je možné povolit / zakázat v nastavení tématu vzhledu)
  $mission Poslání webu (zobrazení je možné povolit / zakázat v nastavení tématu vzhledu)
Navigace
  $search_box Vyhledávací formulář (zobrazení je možné povolit / zakázat v nastavení tématu vzhledu)
  $primary_links Primární odkazy navigace (pokud jsou nastaveny)
  $secondary_links Sekundární odkazy navigace (pokud jsou nastaveny)
$sidebar_left $left Levý postranní pruh
$sidebar_right $right Pravý postranní pruh
Obsah stránky
  $header Identifikace bloku hlavičky
  $breadcrumb "Drobečková" navigace aktuální stránky
  $tabs Záložky s možnostmi aktuální stránky (např. Zobrazit, Upravit...)
  $tabs2  
  $title Název aktuální stránky

$show_messages  
  $messages Stav a chybová hlášení (zvýrazněte pomocí CSS)
  $help Dynamický text nápovědy (většinou pro stránky administrace)
  $content Hlavní obsah aktuální stránky
  $feed_icons Řetězec všech ikonek aktuální stránky (např. Syndikovaný obsah RSS)
Patička
  $footer_message Zápatí webu definované v administraci stránek (Informace o webu)

$footer Oblast zápatí webu
Uzavírací data
  $closure Závěrečná uzavírací značka pro všechny moduly, které mění stránku (uvádějte až za veškerým dynamickým obsahem)

Poznámka:
Pomocí snippetů můžete např. zobrazit uvítání uživatele, nebo upozornit na to, že uživatel ještě není registrován. 

template.php

Šablona template.php (en) umožňuje předefinovat výchozí a vytvářet vlastních funkce.

Odpovídající funkce je možné vyhledat na stránkce Default theme implementations (en).

Odstranění názvu a drobečkové navigace z úvodní stránky

Výraz "template" nahraďte za název tématu.

<?php
function template_preprocess_page(&$variables) {
  //If front page remove title and breadcrumb
  if (drupal_is_front_page()) {
    $variables['breadcrumb'] = '';
    $variables['title'] = '';
  }
}
?>

Potlačení CSS souborů definovaných jádrem a moduly

Téma vzheldu může nahradit CSS soubory definované jádrem a moduly přidáním stylopisu stejného jména a použitím funkce drupal_add_css(). Toto umožňuje tématům potlačit veškeré CSS soubory pokud je to nutné.

Například pokud chcete styl modules/system/system-menus.css definovaný jádrem nahradit (potlačit pro určitá média) vlastním:

  1. V používaném tématu vzhledu vytvořte např. v adresáři styles soubor system-menus.css s požadovanými styly.
  2. V používaném tématu vzhledu vytvořte (upravte) souboru template.php, do kterého vložte:
    <?php
      drupal_add_css(path_to_theme() .'/styles/system-menus.css', 'theme', 'screen, projection', TRUE);
    ?>
    

Výše uvedený příklad se načte pouze pro dané téma, tj. nenačte se pro případná podtémata. Pokud potřebujete používat přepis stylu i v podtématech přidejte jej přímo do .info souboru.

Odstranění zvolených meta tagů

/*​*
* Used to remove certain elements from the $head output within html.tpl.php
*
* @see http://api.drupal.org/api/drupal/modules--system--system.api.php/functio...
* @param array $head_elements
*/
function YOUR_THEME_NAME_html_head_alter(&$head_elements) {
    $remove = array(
        'system_meta_generator',
        'metatag_canonical',
        'metatag_shortlink'
   );
    foreach ($remove as $key) {
        if (isset($head_elements[$key])) {
            unset($head_elements[$key]);
        }
    }
    // Use this loop to find out which keys are available.
    /* -- Delete this line to execute this loop
    echo '<pre>';
    foreach ($head_elements as $key => $element) {
        echo $key ."\n";
    }
    echo '</pre>';
    // */
}

$body_classes

Pro přidání aktuální uživatelské role a cesty (verze A) do pole $body_classes stačí do souboru template.php v používaném tématu vzhledu vložit níže uvedený snippet a změňte MYTHEMENAME na aktuální název tématu vzhledu:

Drupal 7

Verze A

/**
* Add current user's role and path to $body_classes shown in <body>
*/
function MYTHEMENAME_preprocess_html(&$vars) {
  //$body_classes = array($vars['classes_array']); // normal theme
  $body_classes = array($vars['attributes_array']['class']); // omega theme
  if ($vars['user']) {
    foreach($vars['user']->roles as $key => $role) {
      $role_class = 'role-' . str_replace(' ', '-', $role);
      //$vars['classes_array'][] = $role_class; // normal theme
      $vars['attributes_array']['class'][] = $role_class; // omega theme
    }
  }
 
  $path = drupal_get_path_alias($_GET['q']);
  $aliases = explode('/', $path);
  foreach($aliases as $alias) {
    //$vars['classes_array'][] = drupal_clean_css_identifier($alias); // normal theme
    $vars['attributes_array']['class'][] = drupal_clean_css_identifier($alias); // omega theme
  }
}

Verze B

/**
* Add current user's role to $body_classes shown in <body>
*/
function MYTHEMENAME_preprocess_page(&$vars) {
  if ($vars['user']) {
    foreach($vars['user']->roles as $key => $role){
      $vars['class'][] = 'role-' . drupal_html_class($role);
    }
  }
}

Drupal 6

/**
* Add current user's role to $body_classes shown in <body>
*/
function MYTHEMENAME_preprocess_page(&$vars, $hook) {
  $body_classes = array($vars['body_classes']);
   if ($vars['user']) {
    foreach($vars['user']->roles as $key => $role){
      $role_class = 'role-' . str_replace(' ', '-', $role);
      $body_classes[] = $role_class;
    }
  }
  $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}

Funkce vzhledu

Všechny funkce začínající slovem template_ nebo theme_ (např. theme_username) vytvářejí HTML výstup a je možné je upravit pomocí souboru template.php.

Obecný posutp

  1. Najděte požadovanou funkci (přímo v Drupalu nebo na api.drupal.org).
  2. Zkopírujte funci do template.php, přejmenujte její název např. z theme_... nebo template_... nejlépe na název používaného tématu MYTHEMENAME_..., což je zhlediska výkonu nejlepší a upravte dle libosti.
  3. Pro zjištění hodnot pole je vhodné do funkce vložit např. funkci var_dump() nebo kpr() s požadovaným polem
    • var_dump($variables);
      
      kpr($variables);
      
  4. Po úpravách template.php je důležité obnovit cache tématu vzhledu!
    • Přejděte na stránku s tématy vzhledu a aktuální stav uložte.

Příklady

Drupal 7

Přesměrování uživatele na stránku Dashboard ihned po přihlášení:

  • /**
    * Redirect user to a specific page after they login
    */
    function MYTHEMENAME_user_login(&$edit, $account) {
      $edit['redirect'] = 'admin/dashboard';
    }
  • nebo ještě lépe
  • /**
    * Redirect user to a specific page after they login if they belong to a certain role
    */
    function MYTHEMENAME_user_login(&$edit, $account) {
      if (!isset($_POST['form_id']) || $_POST['form_id'] != 'user_pass_reset' || variable_get('login_destination_immediate_redirect', FALSE)) {
        if(in_array('administrator',$account->roles)) {
          drupal_goto('admin/dashboard');
        }
        else {
          drupal_goto('user/'.$account->uid);
        }
      }
    }

Přepis výstupu polí

function MYTHEMENAME_preprocess_field(&$variables, $hook) {
  //kpr($variables);

  // For field type "boolean"
  if ($element['#field_type'] == 'list_boolean') {
    // Add CSS class and change in Value
    if ($variables['element']['#items'][0]['value'] == 1) {
      $variables['classes_array'][] = 'true';
      $variables['items'][0]['#markup'] = t('Yes');
    }
    else {
      $variables['classes_array'][] = 'false';   
      $variables['items'][0]['#markup'] = t('No');
    }
  }   

  // For all field except specific type and name
  if($variables['element']['#field_type'] !== 'text_with_summary' &&
     $variables['element']['#field_type'] !== 'text_long' &&
     $variables['element']['#field_name'] !== 'field_price' {
    // For each item
    foreach ($variables['items'] as $delta => $item) {
      if (!empty($variables['items'][$delta]['#markup'])) {
          // Add tag <strong>
          $variables['items'][$delta]['#markup'] = '<strong>'. $variables['items'][$delta]['#markup'] .'</strong>';
      }
    }
  }
}

Náhrada nulové ceny za slovo zdarma ve výpisu Views:

/**
* Replace price 0 to free
*/
function MYTHEMENAME_preprocess_views_view_fields(&$variables) {
  //kpr($variables);
  if($variables['fields']['field_price']->content == 0) {
    $variables['fields']['field_price']->content = t('free');
  } 
}

Úprava řetězce "Submitted by [name] on [date]":

<?php
function MYTHEMENAME_preprocess_node(&$variables) {
  $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));

  // only username
  //$variables['submitted'] = t('Submitted by !username', array('!username' => $variables['name']));

  // only date
  //$variables['submitted'] = t('Submitted on !datetime', array('!datetime' => $variables['date']));

  // Drupal date formats (long, medium, short)
  //$variables['date'] = format_date($variables['node']->created, 'short');

  // Custom format types
  //$variables['date'] = format_date($variables['node']->created, 'custom', 'F j, Y');

  // Date Created -> Changed
  //$variables['date'] = format_date($node->changed);

  // Date Created -> Changed + custom username and date
  /*$variables['date'] = format_date($node->changed);
  if (variable_get('node_submitted_' . $node->type, TRUE)) {
    $variables['display_submitted'] = TRUE;
    $variables['submitted'] = t('Edited by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));
    $variables['user_picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', array('account' => $node)) : '';
  } else {
    $variables['display_submitted'] = FALSE;
    $variables['submitted'] = '';
     $variables['user_picture'] = '';
  }*/
}
?>

Úprava délky uživatelského jména:

  1. Funkce, která mimo jiné ořezává délku uživatelského jména se jmenuje template_preprocess_username.
  2. Tuto funkci je vhodé doplnit ještě o možnost zobrazení úplného jména pomocí modulu RealName a nově vytvořeného pole field_fullname.
  3. Výsledná funkce může vypadat třeba takto
    • /**​
       * Implements hook_preprocess_username().
      */
      function MYTHEMENAME_preprocess_username(&$variables) {
        $account = $variables['account'];
      
        $variables['extra'] = '';
        if (empty($account->uid)) {
          $variables['uid'] = 0;
          if (theme_get_setting('toggle_comment_user_verification')) {
            $variables['extra'] = ' (' . t('not verified') . ')';
          }
        }
        else {
          $variables['uid'] = (int) $account->uid;
          $user = user_load($account->uid);
          if (isset($user->field_fullname['und'][0]['value'])) {
            $name = $variables['name_raw'] = $user->field_fullname ['und'][0]['safe_value'];
          } 
          else {
            // Set the name to a formatted name that is safe for printing and
            // that won't break tables by being too long. Keep an unshortened,
            // unsanitized version, in case other preprocess functions want to implement
            // their own shortening logic or add markup. If they do so, they must ensure
            // that $variables['name'] is safe for printing.
            $name = $variables['name_raw'] = format_username($account);
          }
        }
      
        if (drupal_strlen($name) > 20) {
          //$name = drupal_substr($name, 0, 15) . '...';
        }
        $variables['name'] = check_plain($name);
        $variables['profile_access'] = user_access('access user profiles');
        $variables['link_attributes'] = array();
        // Populate link path and attributes if appropriate.
        if ($variables['uid'] && $variables['profile_access']) {
          // We are linking to a local user.
          $variables['link_attributes'] = array('title' => t('View user profile.'));
          $variables['link_path'] = 'user/' . $variables['uid'];
        }
        elseif (!empty($account->homepage)) {
          // Like the 'class' attribute, the 'rel' attribute can hold a
          // space-separated set of values, so initialize it as an array to make it
          // easier for other preprocess functions to append to it.
          $variables['link_attributes'] = array('rel' => array('nofollow'));
          $variables['link_path'] = $account->homepage;
          $variables['homepage'] = $account->homepage;
        }
        // We do not want the l() function to check_plain() a second time.
        $variables['link_options']['html'] = TRUE;
        // Set a default class.
        $variables['attributes_array'] = array('class' => array('username'));
      }
Drupal 6
  1. Funkce, která mimo jiné ořezává délku uživatelského jména je v souboru includes/thhme.inc a jmenuje se theme_username.
  2. Funkci zkopírujte do template.php, přejmenujte její název z theme_username na název vašeho tématu MYTHEMENAME_username a upravte požadovanou část jejího kódu:
    function theme_username($object) {
      if ($object->uid && $object->name) {
        // Shorten the name when it is too long or it will break many tables.
        if (drupal_strlen($object->name) > 20) {
          $name = drupal_substr($object->name, 0, 15) .'...';
        }
    ...

    např. na:

    function MYTHEMENAME_username($object) {
      if ($object->uid && $object->name) {
        // Shorten the name when it is too long or it will break many tables.
        if (drupal_strlen($object->name) > 30) {
          $name = drupal_substr($object->name, 0, 25) .'...';
        }
    ...
    

    Místo phptemplate je z hlediska výkonu vhodnější psát název tématu. 

  3. Přejděte na stránku s tématy vzhledu a aktální stav uložte.

 

Navigace

Pro přidání CSS atributů k menu odkazům použijte modul Menu Attributes.

Pokud potřebujete přidat třídy položkám LI použijte funkci theme_menu_link.

  • function YOURTHEME_menu_link__main_menu($variables){
    } 

Pokud potřebujete přidat třídy seznamu UL použijte funkci theme_menu_tree.

Příklady

Doplnění CSS do navigace:

  • /**
    * Overrides theme_menu_tree().
    * Add bootstrap 'navbar-nav' class to Top Navigation menu
    */
    function YOURTHEME_menu_tree__menu_top_navigation(&$variables) {
      return '<ul class="menu nav navbar-nav">' . $variables['tree'] . '</ul>';
    }

Vlastní funkce

Získání argumentů z URL:

$url = arg();
print_r($url);
//print $url[0] .'|'. $url[1];

Získání query parametrů z URL:

$query = drupal_get_query_parameters();
//print_r $query;
print $query['page'];

Doplnění počtu položek menu:

/**
* Process variables for menu-block-wrapper.tpl.php.
*
* @see menu-block-wrapper.tpl.php
*/
function THEMENAME_preprocess_menu_block_wrapper(&$variables) {
  //$variables['classes_array'][] = 'menu-block-' . $variables['delta'];
  $variables['classes_array'][] = 'menu-level-count-'. count(element_children($variables['content']));
}

Připojení CSS pro Internet Explorer:

/**
 * Generates IE CSS links for LTR and RTL languages.
 */
function phptemplate_get_ie_styles() {
  global $language;
  $iecss = "\n";
  $iecss .= '<!--[if (lte IE 7)&(gte IE 5)]>'."\n  ";
  $iecss .= '<link type="text/css" rel="stylesheet" media="screen,
   projection" href="'. base_path() . path_to_theme()
   .'/styles/ie-7.css" />'."\n  ";
  if (defined('LANGUAGE_RTL') && $language->direction ==
   LANGUAGE_RTL) {
    $iecss .= '<link type="text/css" rel="stylesheet" media="screen,
     projection" href="'. base_path() . path_to_theme()
     .'/styles/ie-7-rtl.css" />'."\n  ";
  }
  $iecss .= '<![if lt IE 7]>'."\n    ";
  $iecss .= '<link type="text/css" rel="stylesheet" media="screen, 
   projection" href="'. base_path() . path_to_theme()
   .'/styles/ie-6.css" />'."\n    ";
  if (defined('LANGUAGE_RTL') && $language->direction ==
   LANGUAGE_RTL) {
    $iecss .= '<link type="text/css" rel="stylesheet" media="screen,
     projection" href="'. base_path() . path_to_theme()
      .'/styles/ie-6-rtl.css" />'."\n    ";
  }
  $iecss .= '<![if lt IE 6]>'."\n      ";
  $iecss .= '<link type="text/css" rel="stylesheet" media="screen,
   projection" href="'. base_path() . path_to_theme()
    .'/styles/ie-5.5.css" />'."\n      ";
  if (defined('LANGUAGE_RTL') && $language->direction ==
   LANGUAGE_RTL) {
    $iecss .= '<link type="text/css" rel="stylesheet" media="screen,
     projection" href="'. base_path() . path_to_theme()
     .'/styles/ie-5.5-rtl.css" />'."\n      ";
  }
  $iecss .= '<![if lt IE 5.5]>'."\n        ";
  $iecss .= '<link type="text/css" rel="stylesheet" media="screen, 
   projection" href="'. base_path() . path_to_theme()
   .'/styles/ie-5.css" />'."\n      ";
  if (defined('LANGUAGE_RTL') && $language->direction ==
   LANGUAGE_RTL) {
    $iecss .= "  ".'<link type="text/css" rel="stylesheet"
     media="screen, projection" href="'. base_path() .
      path_to_theme() .'/styles/ie-5-rtl.css" />'."\n      ";
  }
  $iecss .= '<![endif]>'."\n    ";
  $iecss .= '<![endif]>'."\n  ";
  $iecss .= '<![endif]>'."\n";
  $iecss .= '<![endif]-->'."\n";
  return $iecss;
}

 

Úprava formulářů

V používaném tématu vzhledu vytvořte (upravte) soubor template.php, do kterého vložte požadovanou funkci nalezenou přímo v Drupalu nebo na api.drupal.org:

  • /**
    * Implements HOOK_form_alter()
    */
    function MYTHEMENAME_form_alter(&$form, &$form_state, $form_id) {
      //kpr($form); // require Devel modul
      //dpm($form_id); // require Devel modul
      //drupal_set_message($form_id);  // print form ID to messages
      //drupal_set_message(print_r($form, TRUE));  // print array to messages
      //var_dump($form);
    
      //echo $form_id .", ";
    }
  • nebo ještě lépe
  • /**
    * Implements HOOK_form_FORM_ID_alter()
    */
    function MYTHEMENAME_form_search_block_form_alter(&$form, &$form_state, $form_id) {
      //kpr($form); // require Devel modul
      //var_dump($form);
    
      //kpr(); // require Devel modul
    }

Např. modifikace atributů a textu tlačítek:

/**
* Implements HOOK_form_alter()
*/
function MYMODUELNAME_form_alter(&$form, &$form_state, $form_id) {
  if($form_id == 'user_register') {
   // change submit button
    $form['submit']['#value'] = t('Complete the registration');
  }
}
/**
* Implements HOOK_form_alter()
*/
function MYTHEMENAME_form_alter(&$form, &$form_state, $form_id) {
  //var_dump($form);

  // submit input
  if(isset($form['product_id']) && $form_id == 'commerce_cart_add_to_cart_form_' . $form['product_id']['#value']) {
    $form['submit']['#attributes']['title'] = t('Add to Wishlist');
  }
// 1. step of checkout
  if($form_id == 'views_form_commerce_cart_form_default') {
    $form['actions']['continue_shopping']['#value'] = t('Continue');
    $form['actions']['submit']['#value'] = t('Update demand');
    $form['actions']['checkout']['#value'] = t('Send demand');
  }
// 2. step of checkout
  if($form_id == 'commerce_checkout_form_checkout') {
    $form['buttons']['continue']['#value'] = t('Send demand');
  }
}

Příklad úpravy exposed filtru (#process):

/**
* Custom process function
**/
function MYFUNCTION_process($element, $form_state, $form) {
  //print('<pre>'.print_r($form,1).'</pre>');
  //kpr($element);
  //kpr($form_state);

  // First element "CUSTOM_TEXT"
  $element['CUSTOM_TEXT'] =  array(
    '#markup' => "<div class='my-class'>CUSTOM TEXT</div>",
);

  // Second element "MY_LINK"
  $element['MY_LINK'] =  array(
    '#type' => 'link',
    '#prefix' => '<div class="MYCLASS">',
    '#title' => '<span>'. t('TITLE') .'</span>',
    '#suffix' => '</div>',
    '#href' => 'MYURL',
    '#id' => 'prev',
    '#ajax' => array(
      'wrapper' => 'level-form',
      'method' => 'html',
),
    '#options' => array(
      'html' => true,
      'fragment' => 'MY-ANCHOR',
      'attributes' => array(
        'title' => t('HOVER TITLE'),
  ),
      'query' => array(
        'year' => 2013,
        'month' => 9,
  )
),
    '#weight' => -10,
);
  return $element;
}
function HOOK_form_alter(&$form, &$form_state, $form_id) {
  $form['date']['value']['#process'][] = 'MYFUNCTION_process';
  //kpr($form); 
}

...

Date

 Odstranění (úprava) popisu "celý den" u pole datum modulu Date:

/**
* Theme the way an 'all day' label will look.
*/
function phptemplate_date_all_day_label() {
  return '';
}

 Místo phptemplate je z hlediska výkonu vhodnější psát název tématu. 

comment.tpl.php

Soubor comment.tpl.php obsahuje šablonu komentáře

Příklad:

<div class="comment2<?php print ($comment->new) ? ' comment-new' : ''; print ' '. $status; print ' '. $zebra; ?>">
  <div class="clear-block">
  <?php if ($submitted): ?>
    <span class="submitted"><?php print $submitted; ?></span>
  <?php endif; ?>
  <?php if ($comment->new) : ?>
    <span class="new"><?php print drupal_ucfirst($new) ?></span>
  <?php endif; ?>
  <?php print $picture ?>

    <h3><?php print $title ?></h3>
    <div class="content">
      <?php print $content ?>
      <?php
        if ($signature):
        // You can use the following to prevent double-display of signatures on old posts (converting Drupal 5 to Drupal 6)
        // if ($signature && $comment->cid > 3443): // The highest comment ID before upgrading to Drupal 6
      ?>

        <div class="user-signature clear-block">
          <div>—</div>
          <?php print $signature ?>

        </div>
      <?php endif; ?>

    </div>
  </div>
  <?php if ($links): ?>

    <div class="links"><?php print $links ?></div>
  <?php endif; ?>

</div>

 

maintenance-page.tpl.php

Vlastní vzhled webu v offline režimu.

  1. V adresáři vlastního vzhledu vytvořte soubor maintenance-page.tpl.php např. zkopírováním souboru page.tpl.php.
  2. V sites/default/settings.php odkomentujte (i záčátek a konec pole) a definujte téma pro offline režim např.:
    $conf = array(
      'maintenance_theme' => 'my-owns-theme'
    );

 

Úprava vzhledu modulu pomocí šablony .tpl.php

Bližší informace o šablonách naleznete v Template Suggestions.

Příklad upravy úvodní stránky:

  • Drupal 7
    • page.tpl.php (základní šablona je vyžadována vždy )
    • page--front.tpl.php 
  • Drupal 6
    • page.tpl.php (základní šablona je vyžadována vždy )
    • page-front.tpl.php 

Příklad změny vzhledu uživatelského profilu:

  1. Z adresáře modules/user/ zkopírujte do svého tématu vzhledu soubor user-profile.tpl.php.
  2. A admin/settings/performance (Administrace, Nastavení webu, Výkon) vyčistěte Cache.
  3. Upravte zkopírovaný soubor user-profile.tpl.php dle potřeb.

 

Odvozený vzhled

Odovzený vzhled (sub téma) staví na základním tématu vzhledu, čímž vývojářům a designerům šetří mnoho práce.

Dokumentace: Creating a sub-theme

  1. Pro odvozené téma vzhledu vytvořte nový vlastní adresář např. sites/all/theme/my_subtheme (odvozený vzhled může být umístěn "kdekoli" v Drupal struktuře).
  2. Při vytváření odvozeného vzhledu postupujte stejně jako při vytváření vlastního vzhledu (do adresáře s odvozeným vzhledem umisťujte soubory a adresáře), přičemž práci si ulehčíte tím, že budete vkládat pouze odlišné soubory od "základního" vzhledu.
  3. Odvozený vzhled musí obsahovat alespoň soubor s příponou .info např. my-subtheme.info.
  4. Odovzený vzhled sdílí CSS, JavaScript, šablony (*.tpl.php), template.php, náhled.
  5. Odvozený vzhled nesdílí theme-settings.php, logo, favicon, color (modul integraci) a některá nastavení z .info souboru (regions, core version, color info).

Příklad:

name = Odvozené téma vzhledu
description = Popis odvozeného tématu
core = 6.x
engine = phptemplate
base theme = nazev-zakladniho-tematu
stylesheets[screen, projection][] = styles/my-derived-styles.css
scripts[] = my-derived-scripts.js

Název odvozeného tématu je uložen v proměnné $theme_key(hodí se např. při úpravách cest k obrázkům nebo pro třídy CSS):

<?php
  global $theme_key;
  print $theme_key;
?>

 

Drupal CSS standardy

Dokumentace:

CSS formátování

/**
 * @file
 * Short description describing the file.
 *
 * The first sentence of the long description starts here and continues on this
 * line for a while finally concluding here at the end of this paragraph.
 */

/* @group Section comment block
----------------------------------------------------------------------------- */

html,
body {
  min-height: 100%
}


/* @end Section comment block */

/**
 * Short description using Doxygen-style comment format.
 *
 * The first sentence of the long description starts here and continues on this
 * line for a while finally concluding here at the end of this paragraph.
 *
 * The long description is ideal for more detailed explanations and
 * documentation. It can include example HTML, URLs, or any other information
 * that is deemed necessary or useful.
 */
body {
  /* This line is indented with 2 spaces, 2 spaces x 1 level of indentation. */
  text-align: left;
}

/* The example's item styling. */
body,
div,
.selector-3[type="text"] {
  /* Override the default margins. */
  margin: 0;
  padding: 0;
  color: #333;
  background: #fff;
  background: linear-gradient(#fff, rgba(0, 0, 0, 0.8));
  font-family: Times, "Times New Roman", sans-serif;
}

.selector-1,
.selector-2 {
  padding: 10px;
}

  • výchozí standard kódování pro CSS soubory je UTF-8
    • vzhledem k tomu, že při agragaci dochází ke slučování více CSS souborů do jednoho, nesmí CSS soubory obsahovat žádné @charset prohlášení
  • každý soubor by měl začínat komentářem, který by měl soubor popisovat (max. 80 znaků na řádek)
    • pro komentáře je používána Doxygen konvence
  • u dlouhých soubrů vytvářejte pomocí komentářů "oddíly"
  • všechny textové soubory by měly končit prázným řádkem (umožňuje snadnější čtení pro GIT).
  • všechny textové soubory by měly mít Unixové formátování konců řádků (nový řádek \nnebo LF)
    • nastavte si editor tak, aby vám zobrazoval "neviditelné" formátovací znaky
    • Drupal 8 obsahuje v kořenovém adresáři soubor EditorConfig, který pomáhá udržovat tyto konvence mezer
  • selektor se umisťuje hned za komentář (bez prázdného oddělovacího řádku)
  • u více selektorů oddělených čárkou pište každý selektor na nový řádek
  • každou vlastnost piště na samostatný řádek
  • před dvojtečkou a čárkou se mezera nedělá, ovšem za ní ano
  • závorky obklopují svůj obsah přímo bez vložené mezery
  • za každou vlastností pište středník
  • barvy v hexadecimálním tvaru pište malými písmeny a pokud možno ve zkráceném tvaru #ccc (pozor, IE8 nepodporuje všechny barevné syntaxe)
  • víceslovné názvů fontů a hodnoty atributů v selektorech uzavírejte do uvozovek
  • u nulových hodnot nepište jednotky
  • každé pravidlo oddělte prázdným řádkem
  • konce řádků nesmí obsahovat žádné mezery nebo tabulátory

Podpora jazyků s tokem textu Right-To-Left (RTL)

Kaskádové styly je možné vytvářet v párech. Ve stejném adresáři může být např. soubor example.css s výchozím určením pro tok textu zleva doprava (LTR) a example-rtl.css určený pro tok textu zprava doleva (RTL) např. pro Arabštinu, Hebrejštinu atd.

Soubor example-rtl.css může potlačit určené deklarace souboru example.css. Odlišnosti v toku textu označeny /* LTR */ komentářem v originálním souboru example.css, aby bylo jasné které deklarace je nutné modifikovat v souboru example-rtl.css (pro přehlednost při pozdějších úpravách).

Soubor example-rtl.css je uplatněn pouze v případě použití jazyka (zobrazení stránek) s tokem textu zprava doleva a potlačuje tak určené deklarace souboru example.css.

Left-To-Right (LTR) vlastnosti by měly být označeny níže uvedeným komentářem v souboru example.css:

/**
 * @file
 * Left-To-Right (LTR) CSS file example.
 */
.example-rule {
  float: left; /* LTR */
  margin-right: 1.5em; /* LTR */
  padding: 0 0.25em;
}

Při použití RTL jazyka bude načten i příslušný soubor example-rtl.css:

/**
 * @file
 * Right-To-Left (RTL) CSS file example.
 */
.example-rule {
  float: right;
  margin-left: 1.5em;
  margin-right: 0;
}

Pořadí deklarací

.selector {
  /* Positioning */
  position: absolute;
  z-index: 10;
  top: 0;
  left: 0;
  /* Box Model */
  display: inline-block;
  -moz-box-sizing: border-box;
  -ms-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  width: 100px;
  padding: 10px;
  border: 10px solid #333;
  /* Other */
  background: #000;
  color: #fff;
  font-family: sans-serif;
  font-size: 1.1em;
}

Deklarace pište v pořadí od důležitých k méně důležitým:

  1. pozicování: position, float, clear, top, right, bottom, left, direction a z-index
  2. box model: [(max|min)-]height, [(max|min)-]width, margin, padding, border, margin-top atd. včetně box-sizing
  3. další vlastnosti: písmo, text atd.

Výjimky a mírné odchylky

.selector-1 { width: 10%; }
.selector-2 { width: 20%; }
.selector-3 { width: 30%; }

Mnoho jednoduchých deklarací je možné psát "jednořádkovým" formátem s mezerou za otevírací a před uzavírací závorkou.

.selector {
  background-image:
    linear-gradient(#fff, #ccc),
    linear-gradient(#f3c, #4ec);
  box-shadow:
    1px 1px 1px #000,
    2px 2px 1px 1px #ccc inset;
}

Dlouhé hodnoty oddělené čárkou (přechody, stíny atd.) je možné pro zvýšení čitelnosti psát na více řádků.

Příklad

/**
 * @file
 * Example of CSS coding standards for Drupal.
 */

/* ==========================================================================
   Grid layout
   ======================================================================= */

/**
 * Column layout with horizontal scroll.
 *
 * This creates a single row of full-height, non-wrapping columns that can be
 * browsed horizontally within their parent.
 *
 * Example HTML:
 *
 * <div class="grid">
 *   <div class="cell cell-3"></div>
 *   <div class="cell cell-3"></div>
 *   <div class="cell cell-3"></div>
 * </div>
 */

/**
 * Grid container
 *
 * Must only contain `.cell` children.
 */
.grid {
  height: 100%;
  /* Remove inter-cell whitespace */
  font-size: 0;
  /* Prevent inline-block cells wrapping */
  white-space: nowrap;
}

/**
 * Grid cells
 *
 * No explicit width by default. Extend with `.cell-n` classes.
 */
.cell {
  position: relative;
  display: inline-block;
  overflow: hidden;
  box-sizing: border-box;
  height: 100%;
  /* Set the inter-cell spacing */
  padding: 0 10px;
  border: 2px solid #333;
  vertical-align: top;
  /* Reset white-space */
  white-space: normal;
  /* Reset font-size */
  font-size: 16px;
}

/* Cell states */
.cell.is-animating {
  background-color: #fffdec;
}

/* Cell dimensions */
.cell-1 { width: 10%; }
.cell-2 { width: 20%; }
.cell-3 { width: 30%; }
.cell-4 { width: 40%; }
.cell-5 { width: 50%; }

/* Cell modifiers */
.cell--detail,
.cell--important {
  border-width: 4px;
}

Seskupování CSS pravidel

Drupal 8 vychází ze SMACSS kategorizace CSS pravidel.

  1. CSS_BASE – základní styl HTML elementů
  2. CSS_LAYOUT – základní uspořádání webové stránky
  3. CSS_MODULE – opakovaně použitelné komponenty návrhu (Netýká se Drupal modulů)
  4. CSS_STATE – styly závislé na JavaScriptu
  5. CSS_THEME – volitelný vzhled prvky návrhu (Netýká se Drupal témat)

Každá kategorie sad pravidel by měla být v samostatném CSS souboru.

Drupal 8 může mít jen 2 agregované CSS soubory (dříve jich bylo minimálně 6):

  • agregace pro každou stránku (AGGREGATE_EVERY_PAGE)
  • podmíněná agragace (AGGREGATE_CONDITIONAL)

Doporučení

  • každý z vícenásobných CSS selektorů psát na samostatný řádek 
  • barevné nastavení vzhledu (barvy textů, pozadí, rámečků, stínů, obrázky na pozadí) psát do samostatného souboru např. color.css
  • výchozí formátování HTML prvků psát do samostatného souboru např. html.css

 

node.tpl.php

template.php

/**
* Preproccess for Page
*/
function mytheme_process_page(&$variables) {
  // Node type Article title
  if (!empty($variables['node']) && $variables['node']->type == 'article') {
    //kpr($variables['node']);
    $long_title = $variables['node']->field_long_title[LANGUAGE_NONE][0]['safe_value'];
    $variables['title'] = $long_title;
  }
}

function mytheme_preprocess_node(&$variables, $hook) {
  // Node type Article
  if ($variables['node']->type == 'article') {
    //kpr($variables);

    // Getting taxonomy term (only one)
    $tid = $variables['field_categories'][LANGUAGE_NONE][0]['tid'];
    $term = taxonomy_term_load($tid); // load term object
    $term_uri = taxonomy_term_uri($term); // get array with path
    $term_title = taxonomy_term_title($term);
    $term_path = $term_uri['path'];
    $article_link = l($term_title,$term_path);

    // Change date format
    $article_date = date("F d. Y", $variables['created']);

    // Block (#1)
    $block = module_invoke('block','block_view','1');
    $block_whole = block_load('block','1'); // not really the whole block until render

    // Views block ("test")
    $views_block = module_invoke('views','block_view','test_view-block');

    // Creating custom variables for node.tpl.php
    $variables['article_link'] = $article_link;
    $variables['article_date'] = $article_date;
    $variables['block'] = $block;
    $variables['block_whole'] = $block_whole;
    $variables['views_block'] = $views_block;
  }
}

node--article.tpl.php

<div><?php print $article_link ." | ". $article_date; ?></div>
<?php
  print render($block['content']);
  print drupal_render(_block_get_renderable_array(_block_render_blocks(array($block_whole))));
  print render($views_block);
?>
<?php
  // Hide the comments and links
  //hide($content['comments']);
  //hide($content['links']);
  // Render comments and links
  print render($content['links']);
  print render($content['comments']);
?>