JavaScript Integration For Chess Mérida Font Displays

Learning Lab
My Journey Through Books, Discoveries, and Ideas

JavaScript integration for chess Mérida font displays

In my previous post here, I discussed using the Chess Mérida font and specific CSS to manually create HTML representations of chess boards. While effective, this method requires constructing the board string character by character. To streamline this, I developed a JavaScript solution that automatically generates the board HTML from a standard Forsyth–Edwards Notation (FEN) string.

Automating Board Generation with FEN

The idea is to simply provide the FEN string, which compactly describes a chess position, and let JavaScript handle the translation into the Merida font glyphs and HTML structure.

HTML Setup for JavaScript

To use the script, I define a placeholder div element in my HTML. This div needs a specific class (chessboard-base-js for a board without coordinates, or chessboard-js for one with coordinates) and a data-fen attribute containing the FEN string for the desired position.


<!-- Placeholder for a board with coordinates -->
<div class="chessboard-js" data-fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1">
  <!-- Content here will be replaced by the generated board -->
</div>

<!-- Placeholder for a board without coordinates -->
<div class="chessboard-base-js" data-fen="r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -">
  <!-- Optional placeholder content -->
</div>

The JavaScript targets these classes, reads the data-fen attribute, and replaces the div‘s content with the generated board.

JavaScript Logic Explained

The script performs the following steps:

  1. Initialization: It waits for the DOM to be fully loaded and then finds all elements with the classes chessboard-base-js or chessboard-js.
  2. FEN Parsing: For each element found, it retrieves the FEN string from the data-fen attribute. It focuses on the first part of the FEN, which describes the piece placement, splitting it into 8 ranks (rows).
  3. Glyph Mapping: A mapping (FEN_TO_MERIDA_BASE) stores the base Merida character for each FEN piece type (e.g., ‘P’ maps to ‘p’, ‘n’ maps to ‘m’).

const FEN_TO_MERIDA_BASE = {
  'P': 'p', 'N': 'n', 'B': 'b', 'R': 'r', 'Q': 'q', 'K': 'k', // White bases
  'p': 'o', 'n': 'm', 'b': 'v', 'r': 't', 'q': 'w', 'k': 'l'  // Black bases
};
  1. Square Color Determination: A helper function requiresUppercaseMerida(rankIndex, fileIndex) determines if a square at a given position (0-indexed rank and file) corresponds to a “black” square on the board. This is needed because Merida uses different glyphs (lowercase vs. uppercase) for pieces on light versus dark squares. It calculates this based on the sum of the standard board rank (1-8) and file index (0-7).

// Simplified logic: checks if rank+file sum is even
function requiresUppercaseMerida(rankIndex, fileIndex) {
  const boardRank = 7 - rankIndex; // Convert FEN rank index to board rank
  return (fileIndex + boardRank) % 2 === 0; // True for dark squares
}
  1. Piece Glyph Generation: The getPieceChar(fenChar, rankIndex, fileIndex) function takes the FEN character for a piece and its position. It finds the base Merida glyph using the map and then converts it to uppercase if requiresUppercaseMerida returns true.
  2. Empty Square Handling: FEN uses digits (1-8) to denote consecutive empty squares. The script parses these digits and uses another helper function getEmptySquareChar(rankIndex, fileIndex) to determine the correct Merida character for an empty square (‘*’ for light, ‘+’ for dark) based on its position.
  3. HTML Construction: The main function renderChessboard(element) iterates through each FEN rank and each character within the rank. It builds the HTML string for each rank (<div class="rank">...</div>), prepending and appending the correct border characters (standard or coordinate-based depending on the element’s class). It accumulates these rank strings.
  4. Board Injection: Finally, it adds the top and bottom border strings, joins all the HTML parts, and sets the innerHTML of the original placeholder div. It also updates the element’s classes, removing the JS hooks (chessboard-base-js, chessboard-js) and adding the standard chessboard class for styling.

function renderChessboard(element) {
  const fen = element.dataset.fen;
  // ... (FEN parsing, setup) ...

  const boardContent = [];
  boardContent.push(`<div class="rank">${BORDER_TOP}</div>`); // Add top border

  ranksFen.forEach((rankFen, rankIndex) => {
    // ... (Loop through rank characters, call getPieceChar/getEmptySquareChar) ...
    // ... (Build rankHtml string with borders) ...
    boardContent.push(rankHtml);
  });

  const bottomBorder = isWithLettersNumbers ? COMP_BORDER_BOTTOM : BORDER_BOTTOM;
  boardContent.push(`<div class="rank">${bottomBorder}</div>`); // Add bottom border

  element.innerHTML = boardContent.join(''); // Set the generated HTML
  element.classList.remove('chessboard-base-js', 'chessboard-js');
  element.classList.add('chessboard'); // Apply standard styling class
  element.removeAttribute('data-fen');
}

This script allows me to easily insert chess diagrams anywhere on my site just by adding a simple div with the FEN data.

Here are some examples:

For more insights into this topic, you can find the details here.