--=REKLAMA=--

Nadpisywanie szablonem/Układ strony Logowanie

Z Joomla!WikiPL

Źródło strony standardowej

Najpierw podglądamy źródło strony generowane przez standardowy kod Joomla:

<div class="componentheading">Zaloguj</div>
 
   <form action="www.twoja_domena.pl/component/user/" method="post" name="com-login" id="com-form-login">
 
      <table width="100%" border="0" align="center" cellpadding="4" cellspacing="0" class="contentpane">
         <tr>
            <td colspan="2">
               <div>
                  <img src="/jpl_new2/images/stories/key.jpg" align="right" hspace="10" alt="" />
                  Aby zobaczyć tę część witryny, zaloguj się.
                  <br />
                  <br />
               </div>
            </td>
         </tr>
      </table>
 
      <fieldset class="input">
         <p id="com-form-login-username">
            <label for="username">Nazwa użytkownika</label>
            <br />
            <input name="username" id="username" type="text" class="inputbox" alt="username" size="18" />
         </p>
         <p id="com-form-login-password">
            <label for="passwd">Hasło</label>
            <br />
            <input type="password" id="passwd" name="passwd" class="inputbox" size="18" alt="password" />
         </p>
         <p id="com-form-login-remember">
            <label for="remember">Pamiętaj mnie</label>
            <input type="checkbox" id="remember" name="remember" class="inputbox" value="yes" alt="Remember Me" />
         </p>
	   <input type="submit" name="Submit" class="button" value="Zaloguj" />
      </fieldset>
      <ul>
         <li><a href="/jpl_new2/component/user/reset.html">Nie pamiętasz hasła?</a></li>
         <li><a href="/jpl_new2/component/user/remind.html">Nie pamiętasz nazwy?</a></li>
         <li>Nie masz konta? <a href="/jpl_new2/component/user/register.html">Zarejestruj się</a></li>
      </ul>
      <input type="hidden" name="option" value="com_user" />
      <input type="hidden" name="task" value="login" />
      <input type="hidden" name="return" value="aW5kZXgucGhw" />
      <input type="hidden" name="2e03a88f948dd1724736adc87fd0c1d0" value="1" />
   </form>
</div>

Pierwsze, co nam się na pewno nie spodoba, to tabelka obejmująca tekst komunikatu „Aby zobaczyć tę część witryny, zaloguj się.” i jego ilustrację. Nie ma najmniejszego powodu, by te dwa drobne elementy osadzać wewnątrz tabeli - wystarczy je objąć elementem <div>. Kod grupy przycisków można by uznać za zadowalający, gdyby nie zbędne znaczniki przełamania wierszy oraz... niewidoczne wprawdzie na stronie, ale to przecież nie umniejsza ich wagi, nieprzetłumaczone napisy: username, password oraz Remember Me przypisane do atrybutów alt. Mamy zatem co poprawiać.

Przygotowanie

Najpierw musimy znaleźć skrypt generujący standardowy widok tej strony. Strona "Logowanie" obsługiwana jest przez komponent com_user. Zaglądamy zatem w głównym katalogu swojego Joomla do podkatalogu /components/com_user/views. Znajdziemy tam podkatalog ze znaczącą nazwą /login, a w nim podkatalog /tmpl ze skryptami odpowiedzialnymi za wygląd strony Logowanie:

  • default.php - odpowiada za wyświetlanie tytułu strony oraz wywołanie szablonów stron Logowanie (Zaloguj, Wyloguj)
  • default_login.php - odpowiada za wyświetlanie strony Zaloguj
  • default_logout.php - odpowiada za wyświetlanie strony z komunikatem po wylogowaniu
  • default.xml - zawiera definicje parametrów konfiguracyjnych, odpowiedzialnych za prezentację treści strony
  • index.html - plik chroniący przed skanowaniem zawartości katalogu

Łatwo się domyśleć, że nas interesuje teraz głównie plik default_login.php. W katalogu /html swojego szablonu tworzymy podkatalog /com_user/login i kopiujemy do niego:

  • plik default.php, jeśli zechcemy zmienić oznaczenie tytułu strony, który standardowo otoczono znacznikiem div z przypisanym atrybutem klasy componentheading
  • wspomniany plik default_login.php
  • ze względu na bezpieczeństwo - plik index.html.

Modyfikacje

Tytuł strony

Wyświetlanie tytułów strony ustawiane jest w dwóch miejscach - w podstawowych parametrach pozycji menu Logowanie i w parametrach systemowych. Z objaśnień w pomocy podręcznej dowiadujemy się, że jeśli zarządzimy wyświetlanie tytułu, a nie określimy jego brzmienia, to zostanie użyty tytuł pozycji menu. Co prawda sposób ustalania treści tytułu istotny dla nas nie jest, warto wszakże wiedzieć, że w tym przypadku treść pomocy podręcznej nie jest zbyt precyzyjna. Jeśli w parametrach pozycji menu tytułu nie określimy, tekstem tytułu będzie tłumaczenie etykiety LOGIN" pobrane z pliku językowego xx-XX.com_user.ini (np. pl-PL.com_user.ini). Kod generujący tytuły strony umieszczony jest w dwóch skryptach:

  • w pliku default.php oraz
  • w pliku default_login.php

W obu skryptach instrukcje wywołujące tytuł strony objęte zostały znacznikiem div, któremu w otwarciu została przypisana klasa componentheading. W pliku default.php instrukcja ta ma następującą postać:

<?php if ($this->params->get( 'show_page_title', 1)) : ?>
   <div class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <?php echo $this->escape($this->params->get('page_title')); ?>
   </div>
<?php endif; ?>

A w pliku default_login.php, jak poniżej:

<?php if ( $this->params->get( 'show_login_title' ) ) : ?>
   <div class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <?php echo $this->params->get( 'header_login' ); ?>
   </div>
<?php endif; ?>

Zgodnie z HTML i XHTML nagłówki i tytuły otaczamy jednym ze znaczników Hn (h1, h2, h3, h4, h5, h6). Zależnie od konwencji, jaką chcemy zastosować w swoim projekcie, poprawnym oznaczeniem tytułu strony będzie objęcie go znacznikiem h1 lub h2. Ponieważ w tym opracowaniu znacznik h1 rezerwujemy dla tytułu (nazwy) witryny, w zmodyfikowanym kodzie użyjemy znacznika h2. W jednym i drugim przypadku pozostawimy atrybut klasy, dzięki któremu będziemy dysponować - w razie potrzeby dodatkowym selektorem wiążącym ten element strony z regułami stylu. Oto zmodyfikowany kod:

W pliku default.php
<?php if ($this->params->get( 'show_page_title', 1)) : ?>
   <h2 class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <?php echo $this->escape($this->params->get('page_title')); ?>
   </h2>
<?php endif; ?>
W pliku default_login.php
<?php if ( $this->params->get( 'show_login_title' ) ) : ?>
   <h2 class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <?php echo $this->params->get( 'header_login' ); ?>
   </h2>
<?php endif; ?>

Opis strony

Administrator może zdecydować o wyświetleniu na stronie zwięzłej informacji dla użytkowników, komunikującej przeznaczenie strony. Po lewej lub prawej stronie tej informacji może być wyświetlona ilustracja. Kod generujący opis strony znajduje się w pliku default_login.php:

<table width="100%" border="0" align="center" cellpadding="4" cellspacing="0" class="contentpane<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <tr>
      <td colspan="2">
         <?php if ( $this->params->get( 'show_login_title' ) ) : ?>
         <div class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
         <?php echo $this->params->get( 'header_login' ); ?>
         </div>
         <?php endif; ?>
      <div>
      <?php echo $this->image; ?>
         <?php if ( $this->params->get( 'description_login' ) ) : ?>
            <?php echo $this->params->get( 'description_login_text' ); ?>
            <br /><br />
         <?php endif; ?>
      </div>
      </td>
   </tr>
</table>

Jak widać powyżej, tytuł strony oraz tekst opisu zostały osadzone w jednej komórce tabeli obejmującej oznaczonej klasą contentpane[przyrostek_klasystrony]. Co ciekawe, choć w całej tabelce mamy tylko tę jedną komórkę w jednym wierszu, to została ona oznaczona zupełnie niepotrzebnie atrybutem colspan="2" scalającym dwie komórki. Mamy więc iście klasyczny przykład nadmiarowego, niepotrzebnego kodu. Powstrzymajmy się wszakże przed zbyt daleko idącą krytyką. Dopóki bowiem przeglądarki niezbyt radziły sobie z obsługą standardów, taki nadmiarowy kod pozwalał projektantom utrzymać w ryzach zaplanowany układ strony. Dziś trudno byłoby uzasadnić sensowność tego kodu. Usuńmy zeń zatem wszystko co zbędne. Oto zmodyfikowana wersja:

<div class="contentpane<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <!-- tytul strony --> 
   <?php if ( $this->params->get( 'show_login_title' ) ) : ?>
   <h2 class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
      <?php echo $this->params->get( 'header_login' ); ?>
   </h2>
   <?php endif; ?>
   <!-- opis strony i ilustracja -->
   <div>
      <?php echo $this->image; ?>
      <?php if ( $this->params->get( 'description_login' ) ) : ?>
         <?php echo $this->params->get( 'description_login_text' ); ?>
      <?php endif; ?>
   </div>
</div>

Zamiast tabeli zastosowaliśmy tutaj element obejmujący <div> z klasą contenpane[przyrostek_klasystrony]. Element ten równie dobrze mógłby się znaleźć w skrypcie default.php, definiującym podstawowy układ wszystkich stron komponentu com_user. Pozostawimy go jednak w tym skrypcie. Dlaczego? W gruncie rzeczy element ten spełnia tylko jeden cel - dostarcza dodatkowego selektora, z którym można związać reguły stylistyczne. Istotny jest przy tym nie sam element <div>, ale przypisana mu klasa, a dokładniej przyrostek klasy strony. Ustawiając parametry pozycji menu, administrator może określić przyrostek klasy stylu CSS, który nada tej stronie cechy wyglądu odmienne od innych stron czy to tego samego działu (komponentu), czy innych, formatowanych zgodnie z regułami klasy contentpane.

Aby uzyskać więcej informacji na ten temat, zapoznaj się z artykułem Stosowanie przyrostków klas w Joomla! 1.5

Porównajmy to rozwiązanie z rozwiązaniem zastosowanym w szablonie Beez. Oto stosowny kod:

   <!-- tytul strony --> 
   <?php if ( $this->params->get( 'show_login_title' ) ) : ?>	
   <h2 class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">	
   <?php echo $this->params->get( 'header_login' ); ?>
   </h2>
   <?php endif; ?>
   <!-- opis strony i ilustracja -->
   <?php if ( $this->params->get( 'description_login' ) || isset( $this->image ) ) : ?>
   <div class="contentdescription<?php echo $this->params->get( 'pageclass_sfx' );?>">
      <?php if (isset ($this->image)) :
         echo $this->image;
      endif;
      if ($this->params->get('description_login')) : ?>
      <p>
      <?php echo $this->params->get('description_login_text'); ?>
      </p>
      <?php endif;
      if (isset ($this->image)) : ?>
      <div class="wrap_image">&nbsp;</div>
      <?php endif; ?>
   </div>
   <?php endif; ?>

Po pierwsze, projektant tego rozwiązania zupełnie zrezygnował z elementu obejmującego tytuł i opis strony oraz jego ilustrację. Po drugie, elementowi div obejmującemu opis strony i jego ilustrację przypisał atrybut klasy contentdescription[przyrostek_klasystrony]. Po trzecie, tekst opisu został otoczony znacznikiem akapitu (p). Ponadto dodał element <div> oznaczony klasą wrap_image, którego celem jest przygotowanie obszaru strony dla następnego elementu w przypadku, gdy opis zostanie zilustrowany grafiką. O walorach tego zabiegu można się przekonać zwłaszcza w przypadku, gdy standardowa ilustracja (klucze) towarzyszy standardowemu tekstowi opisu (zdanie: „Aby zobaczyć tę część witryny, zaloguj się.”), pobranemu z pliku językowego. Umieszczenie obrazka po lewej stronie powodowałoby nieestetyczne przesunięcie w prawo następnych elementów strony. Szablon Beez został wydany na licencji GNU/GPL, możemy więc wykorzystać zastosowane w nim rozwiązanie w swoim kodzie, który móglby przybrać np. taki kształt:

<div class="contentpane<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
   <!-- tytul strony --> 
   <?php if ( $this->params->get( 'show_login_title' ) ) : ?>
   <h2 class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>">
      <?php echo $this->params->get( 'header_login' ); ?>
   </h2>
   <?php endif; ?>
   <!-- opis strony i ilustracja -->
   <?php if ( $this->params->get( 'description_login' ) || isset( $this->image ) ) : ?>
   <div class="contentdescription<?php echo $this->params->get( 'pageclass_sfx' );?>">
      <?php if (isset ($this->image)) :
         echo $this->image;
      endif;
      if ($this->params->get('description_login')) : ?>
      <p>
      <?php echo $this->params->get('description_login_text'); ?>
      </p>
      <?php endif;
      if (isset ($this->image)) : ?>
      <div class="wrap_image">&nbsp;</div>
      <?php endif; ?>
   </div>
</div>

Komponenty formularza logowania

W oryginalnym skrypcie komponenty wszystkie komponenty formularza zostały zgrupowane w znaczniku <fieldset>:

<fieldset class="input">
   <p id="com-form-login-username">
      <label for="username"><?php echo JText::_('Username') ?></label><br />
      <input name="username" id="username" type="text" class="inputbox" alt="username" size="18" />
   </p>
   <p id="com-form-login-password">
      <label for="passwd"><?php echo JText::_('Password') ?></label><br />
      <input type="password" id="passwd" name="passwd" class="inputbox" size="18" alt="password" />
   </p>
      <?php if(JPluginHelper::isEnabled('system', 'remember')) : ?>
   <p id="com-form-login-remember">
      <label for="remember"><?php echo JText::_('Remember me') ?></label>
      <input type="checkbox" id="remember" name="remember" class="inputbox" value="yes" alt="Remember Me" />
   </p>
      <?php endif; ?>
      <input type="submit" name="Submit" class="button" value="<?php echo JText::_('LOGIN') ?>" />
</fieldset>

Wspomnieliśmy już wcześniej o dwóch zastrzeżeniach - zbędnym znaczniku <br /> niepotrzebnie przełamującym wiersz za etykietą pola oraz o nieprzetłumaczonych napisach umieszczonych w atrybutach alt. Oczywiście, jeśli chcemy zostawić etykiety nad polami tekstowymi, zamiast obok - znacznik <br /> można pozostawić. Ponieważ jednak na stronie Logowanie nic więcej w obszarze treści głównej - poza formularzem logowania i ewentualnym opisem - nie mamy, umieszczenie etykiet po lewej stronie opisywanych pól da nam w efekcie nieco "pełniejszą" stronę. Dodajmy jeszcze jedną usterkę - etykiety i pola tekstowe otoczone zostały znacznikami <p>, a przecież nie są to akapity. Właściwszym będzie tutaj zastosowanie elementu ogólnego <div>. Oto kod po modyfikacji. Dodatkowo każdemu elementowi przypisaliśmy klasę formlogin, aby dysponować jeszcze jednym selektorem wiążącym style.

<fieldset class="input">
   <div id="com-form-login-username" class="formlogin">
      <label for="username"><?php echo JText::_('Username') ?></label>
      <input id="username" name="username" type="text" class="inputbox" alt="<?php echo JText::_('Username') ?>" size="28" />
   </div>
   <div id="com-form-login-password" class="formlogin">
      <label for="passwd"><?php echo JText::_('Password') ?></label>
      <input id="passwd" name="passwd" type="password" class="inputbox" size="28" alt="<?php echo JText::_('Password') ?" />
   </div>
      <?php if(JPluginHelper::isEnabled('system', 'remember')) : ?>
   <div id="com-form-login-remember" class="formlogin">
      <label for="remember"><?php echo JText::_('Remember me') ?></label>
      <input id="remember" name="remember" type="checkbox" class="inputbox" value="yes" alt="<?php echo JText::_('Remember me') ?>" />
   </div>
      <?php endif; ?>
      <input type="submit" name="Submit" class="button" value="<?php echo JText::_( 'BUTTON_LOGIN' ); ?>" />		
   </fieldset>

Formatowanie formularza

/*
------------------------------------------------------
formatowanie formularza na stronie Logowanie
------------------------------------------------------
*/
#login label {
   float                     : left;
   margin-right              : 0.5em;
   text-align                : right;
   width                     : 10em;
}
#login .inputbox  {
   background-color          : #F2F4F7;
}
.formlogin {
   float                     : left; 
   width                     : 100%;
}
#com-form-login-remember {
   margin-top                : 1.5em;
}
#login .button {
   margin-left               : 19.5em;
   margin-top                : -1.2em;
}
#login ul {
   border-top                : 1px dotted #345AAA;
   list-style                : none outside none;
   margin-top                : 1em;
}
 
#login ul {
   margin                    : 0;
   padding                   : 0;
   margin-top                : 1em;
   padding-top               : 1em;
}
#login ul li {
   list-style                : none outside none;
   background                : url(../images/loginli.png) no-repeat scroll left center transparent;
   padding                   : 0 0 0 18px;
}
#login li {
   margin-left               : 0;
   padding-left              : 0;
}
#login a {
   text-decoration           : none;
}
#login a:hover {
text-decoration              : underline;
}

Dziękujemy za wkład

» Stefan Wajda [zwiastun],