Cómo hacer un login AJAX alternativo

El login normal de Drupal es un formulario que, en caso de error, conduce a otra página. El objetivo es un formulario que use AJAX para el login y permita mostrar los mensajes de error sin cargar otra página.



El bloque
Creo un bloque (my-login) con este contenido:

<?php
global $user;
?>

<?php if ($user->uid): ?>

  <div id="block-my-login">
    <div class="title"><?php echo l(t('Login'), 'user', array('attributes'=>array('id'=>'btn-my-login'))) ?></div>
    <div class="content">
      <ul>
        <li>
          <?php echo l(t('Mi cuenta'), 'user') ?>
        </li>
        <li>
          <?php echo l(t('Salir'), 'logout') ?>
        </li>
      </ul>
    </div>
  </div>

<?php else: ?>

  <div id="block-my-login">
    <div class="title"><?php echo l(t('Login'), 'user', array('attributes'=>array('id'=>'btn-my-login'))) ?></div>
    <div class="content">
      <form id="user-login">
        <div class="username">
          <label><?php echo t('Usuario') ?></label><input type="text" id="name" name="name" class="input text"/>
        </div>
        <div class="password">
          <label><?php echo t('Contraseña') ?></label><input type="password" id="password" name="password" class="input password"/>
        </div>
        <div class="submit">
          <input type="submit" id="submit" value="<?php echo t('Entrar') ?>" class="button submit"/>
        </div>
      </form>
      <div id="loginresult"></div>
      <div class="remember">
        <?php echo l(t('Olvidé mi contraseña'), 'user/password', array('attributes'=>array('id'=>'remember'))) ?>
      </div>
      <div class="register">
        <input type="button" id="register" value="<?php echo t('Registrarme') ?>" class="button register"/>
      </div>
    </div>
  </div>

<?php endif ?>

<?php
  drupal_add_js(drupal_get_path('module', 'misc') . '/js/login.js');
?>

El bloque muestra un formulario simple para el login y una lista de enlaces para el usuario ya logueado.

Javascript
misc/js/login.js contiene el javascript:

$(function() {
  $('#block-my-login .title')
    .click(function(e) {
      e.preventDefault();
      $('#botones-verdes .content').slideUp('slow');
      $('.content', $(this).parent()).slideToggle('slow');
      return false;
    });
  $('#user-login').submit(function() {
    var url = Drupal.settings.basePath + 'user/login.json';
    $.post(url, $(this).serialize(), function(data) {
      var result = Drupal.parseJson(data);
      if (!result.error || result.error == 0) {
        window.location.href = Drupal.settings.basePath + 'user';
      } else {
        $('#loginresult').show().html(result.result);
      }
    });
    return false;
  });
  $('#register').click(function(e) {
    e.preventDefault();
    window.location.href = Drupal.settings.basePath + 'user/register';
    return false;
  });
});

El script invoca a la acción user/login.json, definida en el módulo misc.

Acción
En el módulo misc, para la acción user/login.json:

/**
 * Implements hook_menu
 */
function misc_menu() {
  ...
  $items['user/login.json'] = array(
    'page callback' => 'misc_login_json',
    'access callback' => 'user_is_anonymous',
  );
  return $items;
}
...
function misc_login_json() {
  if (!isset($_POST['name']) && !isset($_POST['password'])) {
    echo json_encode(array('error'=>t('Se requiere $_POST[\'name\'] y $_POST[\'password\']')));
    return;
  }
  $name = $_POST['name'];
  $password = $_POST['password'];
  if ($msg = user_validate_name($name)) {
    echo json_encode(array('error'=>1, 'result'=>$msg));
    return;
  }
  $account = user_load(array('name' => $name, 'pass' => $password, 'status' => 1));
  if ($account) {
    user_external_login($account);
    echo json_encode(array('result'=>'OK'));
    return;
  } else {
    echo json_encode(array('error'=>1, 'result'=>t('Por favor verifique su nombre de usuario y contraseña.')));
    return;
  }
  return;
}

Comentarios

Entradas populares de este blog

Debug con Xdebug y Aptana (y Notepad++)

CSS3 para mejorar el breadcrumb de un tema Zen

Drupal sí, drupal no