Documentación

Referencia de JavaScript

R, el objeto que puede leer cualquier script del sitio, y los eventos que lanza al cambiar de página.

Todo sitio de Rolea pone en la página un objeto llamado R. Te dice quién está leyendo, con cuál de sus personajes juega y en qué página está. También te avisa cuando algo de eso cambia.

Todo lo que hay en R ya está en la página cuando tu script se ejecuta. No tienes que pedir nada de ello, ni tienes que esperarlo.

Qué te da R

PropiedadQué es
R.memberQuien está leyendo, o null si no hay nadie con la sesión iniciada.
R.charactersTodos sus personajes. Una lista vacía si es una visita.
R.characterAquel con el que juega ahora mismo, o null si no ha elegido ninguno.
R.siteEl sitio: su nombre, su idioma y su aspecto.
R.pageQué página está en pantalla y de qué va.
R.versionQué versión de este contrato admite el sitio. Ver Versiones.

R está disponible también como Rolea, por si algo más en la página ya usa un nombre tan corto.

La persona

R.member = {
  login: "nocturna",          // the name they signed up with
  role: "administrator",      // "member" | "moderator" | "administrator" | "founder"
  avatarUrl: "https://…"      // or null
}

Los personajes

R.characters es una lista y R.character es el que está seleccionado ahora. Los dos tienen la misma forma:

R.character = {
  id: "6f2a…",
  slug: "aldric-vane",        // the name in the address bar
  name: "Aldric Vane",
  state: "active",            // "active" | "disabled" | "pending" | "draft"
  avatarUrl: "https://…",     // or null
  faction: {                  // or null, if the character has no faction
    key: "b5c1…",             // its identifier, unchanged by a rename
    slug: "lobos-de-invierno",// its name, ready for a selector
    name: "Lobos de Invierno",
    color: "#8a3b2e"
  }
}

El sitio

R.site = {
  name: "Valdrath",
  locale: "es",               // "es" | "en"
  layout: "modern",           // "modern" | "classic"
  colorScheme: "auto",        // "light" | "dark" | "auto"
  skin: { slug: "ravenwood", version: "1.2.0" }   // or null
}

La página

R.page le da a la página un nombre propio, de modo que un script que decide según él sigue funcionando aunque la dirección cambie:

R.page = {
  route: "scene",             // the name of this kind of page
  path: "/scenes/la-taberna", // the address, without the query string
  params: { slug: "la-taberna" }
}

Todas las páginas tienen una ruta. Estas son las que más vas a querer:

routeLa página
homeLa portada
scenes / sceneLa lista de escenas / una escena
characters / character-profileLa lista de personajes / un personaje
character-dossierLa ficha de un personaje
forum, forum-section, forum-threadEl foro, una sección, un tema del foro
placeUn lugar
market, messages, calendarMercado, mensajes privados, calendario
member-profileEl perfil de una persona
administration / moderationLos paneles de administración y moderación

Una página con algo que merezca la pena saber añade un campo propio. La vista de escena añade scene:

R.page = {
  route: "scene",
  path: "/scenes/la-taberna",
  params: { slug: "la-taberna" },
  scene: {
    id: "1c9e…",
    slug: "la-taberna",
    title: "La taberna del Ancla Rota",
    openness: "public",       // "public" | "private" | "restricted"
    isFinished: false,
    place: { slug: "puerto-viejo", name: "Puerto Viejo" },
    ownerCharacter: { slug: "aldric-vane", name: "Aldric Vane" },
    participantCount: 4,
    wordCount: 12840
  }
}

R.page.scene solo aparece en la vista de escena, así que compruébalo antes de usarlo. Con el tiempo más páginas traerán el suyo; una que no traiga nada extra te sigue dando route, path y params.

Reaccionar a los cambios

Un sitio de Rolea no se recarga al moverte por él, así que el evento de carga de la página se lanza una vez y nunca más. R.on() es como te enteras de todo lo que pasa después.

R.on("page", function (page) {
  console.log("now reading", page.route);
});

Hay tres cosas a las que escuchar:

EventoSe lanza cuandoTu función recibe
"page"Se pasa a otra páginaEl nuevo R.page
"character"Se cambia de personaje, o se deja de elegir unoEl nuevo R.character, o null
"member"Se inicia o se cierra la sesiónEl nuevo R.member, o null

R.on() devuelve una función que deja de escuchar, por si alguna vez la necesitas:

var stop = R.on("character", paintBanner);
// later
stop();

Dar estilo sin nada de JavaScript

Antes de escribir un script, mira si el CSS ya lo resuelve. El sitio mantiene ese mismo contexto en forma de clases en el elemento <html>, así que una hoja de estilos puede responder a él por su cuenta:

html[data-route="scene"] .skeleton__main { max-width: 70ch }
html[data-auth="guest"] .sidebar__compose { display: none }
html[data-faction="lobos-de-invierno"] { --color-brand-primary: #8a3b2e }

La lista completa está en la referencia de CSS. Cuando el CSS puede resolverlo, prefiérelo: se aplica antes de que la página se dibuje.

Recetas

Saludar con el nombre del personaje

R.on("character", function (character) {
  var slot = document.querySelector(".skeleton__topHeader");
  if (!slot) return;
  slot.setAttribute(
    "data-greeting",
    character ? "Bienvenido, " + character.name : ""
  );
});

Marcar las escenas terminadas

R.on("page", function (page) {
  document.body.classList.toggle(
    "is-finished-scene",
    page.route === "scene" && page.scene !== undefined && page.scene.isFinished
  );
});

Algo que solo ve el equipo

var role = R.member ? R.member.role : null;
if (role === "administrator" || role === "founder") {
  document.body.classList.add("has-staff-tools");
}

Buenas prácticas

  • Nunca pidas lo que R ya tiene. La persona, sus personajes y la página actual están ahí gratis. Volver a pedírselos al sitio hace más lenta cada visita.
  • Escribe funciones que puedan ejecutarse más de una vez. Una función de page puede volver a ejecutarse para la misma página según se completa el resto de sus datos. Poner una clase, un atributo o un texto se puede repetir sin daño. Añadir un elemento no, así que comprueba antes si ya lo habías añadido.
  • Lee de R cuando lo necesites, no una vez al principio. R.member y compañía siempre te dan el valor actual. Una copia guardada al cargar se queda obsoleta en cuanto se cambia de personaje.
  • Trata lo que recibes como solo lectura. Los objetos que te da R no se pueden modificar. Copia uno antes de cambiar nada.
  • Contempla siempre el caso vacío. R.member, R.character y la faction de un personaje pueden ser null. En un sitio público, la mayoría de las visitas no tienen sesión.
  • No des por hecho que un elemento está. Los nombres de clase de los bloques son estables, pero lo que hay dentro se mueve. Protege cada querySelector y añade sobre lo que ya hay en la página en vez de reconstruirlo.
  • No toques los paneles. Nada de lo que escribas debería afectar a las páginas de administración o de moderación. R.page.route te dice cuándo estás en una, y un script que oculte parte de un panel puede dejar a una persona administradora fuera de su propio sitio.
  • Que sea pequeño. Tu archivo se carga en cada visita. Los scripts de la cabecera se ejecutan antes de que la página se dibuje, así que pon al final de la página todo lo que no sea urgente.
  • Pruébalo con el sitio en limpio. Añadir ?noskin=1 a cualquier dirección la carga sin tema, sin CSS propio y sin JavaScript propio. Úsalo para distinguir tu trabajo del del sitio, y para poder volver a entrar si algo que escribiste sale mal.

Versiones

R.version es la versión de este contrato que implementa el sitio. Los campos y los eventos nuevos se añaden sin cambiarla, así que un script escrito hoy sigue funcionando. El número solo cambia si alguna vez se renombra o se quita algo, y eso se anuncia antes.