World Wild Web > ☔︎ ∙ I need Help!

(tutorial?) FFXIV pages!

(1/2) > >>

loren:
the (unofficial) melonland FFXIV topic sent me down a rabbit viera hole... i started thinking, "why am i linking people to my character's page on the lodestone, which is kind of ugly? i have a website, can't i make my own page?"

2024/01/17 update: it's broken :(

this led me to XIVAPI, which lets you access game data in a JSON format. before this week, i had no experience with javascript and no idea what JSON was, but with the help of this mdn web docs guide, i was able to put something simple together.

here's the javascript for retrieving your character's name, active class, and class levels (broken up into subgroups, because the list ends up way too long for styling purposes otherwise):


--- Code: ---async function populate() {

  const requestURL = 'https://xivapi.com/character/37508137'; // put your character ID here! //
  const request = new Request(requestURL);

  const response = await fetch(request);
  const charInfo = await response.json();

  populateHeader(charInfo);
  populateTank(charInfo);
  populateHealer(charInfo);
  populateMelee(charInfo);
  populateRanged(charInfo);
  populateMage(charInfo);
  populateCrafter(charInfo);
  populateGatherer(charInfo);

}

function populateHeader(obj) {
  const header = document.querySelector('header');
  const myH1 = document.createElement('h1');
  myH1.textContent = obj.Character.Name;
  header.appendChild(myH1);

  const myH2 = document.createElement('h2');
  myH2.textContent = `Active Class: ${obj.Character.ActiveClassJob.UnlockedState.Name}`;
  header.appendChild(myH2);
}

function populateTank(obj) {
  const section = document.getElementById("tanks");
  const tanks = obj.Character.ClassJobs.slice(0, 4);

  for (const tank of tanks) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${tank.UnlockedState.Name}: ${tank.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateHealer(obj) {
  const section = document.getElementById("healers");
  const healers = obj.Character.ClassJobs.slice(4, 8);

  for (const healer of healers) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${healer.UnlockedState.Name}: ${healer.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateMelee(obj) {
  const section = document.getElementById("melee");
  const melees = obj.Character.ClassJobs.slice(8, 13);

  for (const melee of melees) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${melee.UnlockedState.Name}: ${melee.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateRanged(obj) {
  const section = document.getElementById("ranged");
  const rangeds = obj.Character.ClassJobs.slice(13, 16);

  for (const ranged of rangeds) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${ranged.UnlockedState.Name}: ${ranged.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateMage(obj) {
  const section = document.getElementById("mages");
  const mages = obj.Character.ClassJobs.slice(16, 20);

  for (const mage of mages) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${mage.UnlockedState.Name}: ${mage.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateCrafter(obj) {
  const section = document.getElementById("crafters");
  const crafters = obj.Character.ClassJobs.slice(20, 28);

  for (const crafter of crafters) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${crafter.UnlockedState.Name}: ${crafter.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

function populateGatherer(obj) {
  const section = document.getElementById("gatherers");
  const gatherers = obj.Character.ClassJobs.slice(28, 31);

  for (const gatherer of gatherers) {
    const myArticle = document.createElement('article');
    const myPara1 = document.createElement('p');

    myPara1.textContent = `${gatherer.UnlockedState.Name}: ${gatherer.Level}`;

    myArticle.appendChild(myPara1);

    section.appendChild(myArticle);
  }
}

populate();
--- End code ---

and then in your page's <body></body> you could put something like this:


--- Code: ---<header></header>

<div id="tanks">
  <h3>Tanks:</h3>
</div>

<div id="healers">
  <h3>Healers:</h3>
</div>

<div id="melee">
  <h3>Melee:</h3>
</div>

<div id="ranged">
  <h3>Ranged:</h3>
</div>

<div id="mages">
  <h3>Casters:</h3>
</div>

<div id="crafters">
  <h3>Crafters:</h3>
</div>

<div id="gatherers">
  <h3>Gatherers:</h3>
</div>
--- End code ---

is this totally redundant to the lodestone? yes. would it be easier manually update my character's levels? also yes. but i learned something new! and it's fully customizable :tongue:

i still have a lot to learn, like how to display achievement, mount, and minion data, but i figured i'd share what i have so far in case anyone here is interested in doing something similar.

sig:
I like it, it's definitely useful for intergration with a personal site and I might just end up using it!

debleb:
woah, neat! i might implement this if i ever make a dedicated ffxiv page :P a lot better than linking the lodestone!

Necrosia:
I love you for this  :ozwomp:  :ozwomp:
Will definitively make one for myself and my partner!

loren:
thank you all! i'll keep sharing more code as i figure it out and i hope you'll share what you make with it!  :transport:

here's my work in progress: https://ribo.zone/ffxiv/fio


also, i just found out that the official fan kit has some code for including lodestone tooltips on your website!



Navigation

[0] Message Index

[#] Next page

Go to full version