Темизируем блок входа в систему

Главные вкладки

Аватар пользователя wazzup wazzup 29 октября 2009 в 21:09

Появилась необходимость внести в стандартный блок авторизации некоторые изменения. Такие как: перенести ссылку регистрации над полями ввода, и сменить заголовки полей ввода и кнопок более короткими. Для того чтоб узнать что и как делается, посмотрим для начала на то как сверстан данный блок. Узнаем что: блок имеет id равный block-user-0.
попробуем поискать, как данный блок формируется в модуле /modules/user/user.module
Ищем текст: 'user_block'
Находим: находим функцию function user_block($op = 'list', $delta = 0, $edit = array())
В ней нас интересует следующий кусок:

    switch ($delta) {
      case 0:
        // For usability's sake, avoid showing two login forms on one page.
        if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {

          $block['subject'] = t('User login');
          $block['content'] = drupal_get_form('user_login_block');
        }
        return $block;

а точнее drupal_get_form('user_login_block'); В результате поиска строки 'user_login_block' находим функцию в которой определена форма входа в систему используемая в данном блоке :

function user_login_block() {
  $form = array(
    '#action' => url($_GET['q'], array('query' => drupal_get_destination())),
    '#id' => 'user-login-form',
    '#validate' => user_login_default_validators(),
    '#submit' => array('user_login_submit'),
  );
  $form['name'] = array('#type' => 'textfield',
    '#title' => t('Username'),
    '#maxlength' => USERNAME_MAX_LENGTH,
    '#size' => 15,
    '#required' => TRUE,
  );
  $form['pass'] = array('#type' => 'password',
    '#title' => t('Password'),
    '#maxlength' => 60,
    '#size' => 15,
    '#required' => TRUE,
  );
  $form['submit'] = array('#type' => 'submit',
    '#value' => t('Log in'),
  );
  $items = array();
  if (variable_get('user_register', 1)) {
    $items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.'))));
  }
  $items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.'))));
  $form['links'] = array('#value' => theme('item_list', $items));
  return $form;
}

Вредный совет: собственно можно ограничиться исправлением данной функции и дальше не читать получить кучу проблем, если вдруг появиться необходимость обновить движок

Мы идем другим путём а поэтому мы в модуле user ищем user_theme() и смотри зарегистрирована ли функция темизации для 'user_login_block' . Не находим таковой. Соответственно нам нужно зарегистрировать ее в своей теме для этого откроем файл template.php внутри нашей темы оформления и в нем ищем функцию: НазваниеНашейТемы_theme()
если такой нет, то создаем. Со следующим содержанием:

function НазваниеНашейТемы_theme() {
  return array(
    'user_login_block' => array(
    'arguments' => array('form' => NULL),
    ),
  );
}

Если же она есть. То достаточно будет добавить к возвращаемому ею массиву элемент соответствующий выделенному куску кода. Данный шаг позволит нам изменять данные отданные функцией user_login_block() определив в нашем шаблоне функцию темизации. Теперь можно определить в template.php следующую функцию:

function НазваниеНашейТемы_user_login_block($form) {
  $output = '';
  $form['links']=array();
  if (variable_get('user_register', 1)) {
  $form['links']['#value'] =l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.'))));;
  }
  $form['submit']['#type'] = 'submit';
  $form['submit']['#value']= t('Entrance');
  $form['name']['#title'] = t('Login');
  $output .= drupal_render($form['links']);
  $output .= drupal_render($form);
  return $output;
}

Немного о том, как это работает. Вызывая drupal_render($form['links']); он как бы помечает, что элемент формы 'links' уже выведен. И соответственно при последующем вызове drupal_render($form); он выводит только оставшиеся элементы формы.

Важно: если вы вывели все элементы формы вручную послдователными вызовами drupal_render для отельных элементов, то после этого обязательно надо вызвать drupal_render($form) дабы получить полноценную работающую форму

Теперь поместим подписи за полями ввода и напишем небольшого скрипта, который будет прятать/показывать подписи при фокусе на поле ввода/выходе из него.

Для начала изменим стили

#block-user-0 #user-login-form .form-item input { background:transparent;       }
#block-user-0 #user-login-form .form-item label { display:none;}
#block-user-0 #user-login-form .form-item label.unhide {margin-bottom: -22px; display:block;}

потом внесем изменения в функцию темизации: function НазваниеНашейТемы_user_login_block($form)
добавив перед return $output; такой кусок:

  drupal_add_js('//<![CDATA[
            //
                                $(document).ready(function(){
                               
                        $("#block-user-0 #user-login-form input[value='
."''".']").prev("label").addClass("unhide");        
         
                                $("#block-user-0 #user-login-form input").blur(function () {
                                 if(!$(this).val()) {
         $(this).prev("label").addClass("unhide");
          }
                });
                $("#block-user-0 #user-login-form input").focus(function () {
                                 
         $(this).prev("label").removeClass("unhide");
         
                });
                        });
                        //]]>
  '
,'inline');

}

Остается убрать двоеточия и звездочки которые механизм рендеринга друпала добавляет к подписям полей. Для этого можно либо заменить текст с помощью стилей на изображение. Либо темизировать вывод подписей к полям ввода. Что мы и будем делать.

Исследовав /includes/form.inc находим:

function theme_form_element($element, $value) {
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  $output = '<div class="form-item"';
  if (!empty($element['#id'])) {
    $output .= ' id="'. $element['#id'] .'-wrapper"';
  }
  $output .= ">\n";
  $required = !empty($element['#required']) ? '<span class="form-required" title="'. $t('This field is required.') .'">*</span>' : '';

  if (!empty($element['#title'])) {
    $title = $element['#title'];
    if (!empty($element['#id'])) {
      $output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
    else {
      $output .= ' <label>'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
  }

  $output .= " $value\n";

  if (!empty($element['#description'])) {
    $output .= ' <div class="description">'. $element['#description'] ."</div>\n";
  }

  $output .= "</div>\n";

  return $output;
}

Скопируем ее полностью в свой шаблон, заменив в названии функции theme на название своей темы НазваниеНашейТемы_form_element($element, $value). Поскольку нам надо убрать двоеточия и звездочки только в одном отдельно взятом блоке то мы заменим толко сторки:
      $output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
и
    $output .= ' <label>'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";

Обвернув двоеточие конструкцией: : получим:

$output .= ' <label for="'. $element['#id'] .'">'. $t('!title<span class="colon">:</span> !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";

и

$output .= ' <label>'. $t('!title<span class="colon">:</span> !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";

И с помощью стилей уберем ненужные нам элементы:

#block-user-0 #user-login-form .form-item label,
#block-user-0 #user-login-form .form-item label .form-required,
#block-user-0 #user-login-form .form-item label .colon
{
display:none;
}

Останется только придать результату нужный вам вид с помощью стилей.

Комментарии

Аватар пользователя kuzyakiev@drupal.org kuzyakiev@drupal.org 24 марта 2010 в 18:13

Спасибо за <span class="colon">:</span>. И судя по всему это if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) я тоже здесь почерпнул.
Твоя статья + гугл упростило мне жизнь минимум часа на три)
>баян. формочки можно в теме раскраивать.
удачи)