Home Entrance Everyone Wiki Search Login Register

Welcome, Guest. Please login or register. - Thinking of joining the forum??
April 19, 2024 - @795.35 (what is this?)
Forum activity rating: Three Star Posts: 43/1k.beats Unread Topics | Unread Replies | Own Posts | Own Topics | Random Topic | Recent Posts
News: :ozwomp: Reminder: Forum messages stay readable for years! Keep yours high quality! :ozwomp:

+  MelonLand Forum
|-+  World Wild Web
| |-+  ✁ ∙ Web Crafting
| | |-+  ☔︎ ∙ I need Help!
| | | |-+  (tutorial?) FFXIV pages!


« previous next »
Pages: [1] Print
Author Topic: (tutorial?) FFXIV pages!  (Read 793 times)
loren
Jr. Member ⚓︎
**


StatusCafe: ribose
iMood: ribose

View Profile WWW

First 1000 Members!spring 2023!Learning to swim!Joined 2022!
« on: March 24, 2023 @648.77 »

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();

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>

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.
« Last Edit: January 17, 2024 @844.18 by loren » Logged
sig
Sr. Member ⚓︎
****


the great

iMood: sigmatic

View Profile WWW

First 1000 Members!Certified chocoboGoose!Joined 2022!
« Reply #1 on: March 24, 2023 @652.37 »

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

          
The world ends with you. If you want to enjoy life, expand your world. You gotta push your horizons out as far as they go.
debleb
Full Member ⚓︎
***


He/him, scaley tailey dragon


View Profile WWW

First 1000 Members!Goose!Pocket Icelogist!High Speed Ozwomp!Joined 2022!
« Reply #2 on: March 24, 2023 @761.50 »

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

"I would have thought you to be above something so banal as despair. Am I mistaken?"

Necrosia
Full Member ⚓︎
***


Lord of the Labyrinth


View Profile WWW

First 1000 Members!spring 2023!Welcome Soup!Joined 2023!
« Reply #3 on: March 24, 2023 @769.42 »

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



 
Avatar by Urubu
loren
Jr. Member ⚓︎
**


StatusCafe: ribose
iMood: ribose

View Profile WWW

First 1000 Members!spring 2023!Learning to swim!Joined 2022!
« Reply #4 on: March 24, 2023 @849.25 »

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!



Logged
minttea
Casual Poster ⚓︎
*


very tired...


View Profile WWW

First 1000 Members!Joined 2023!
« Reply #5 on: April 07, 2023 @4.61 »

Oh!! What an interesting concept. Unfortunately, the code didn't mix well with my WOL's OC page, but when I made it a seperate page it worked great! Thanks for the tutorial, I never would have thought to try this!
Logged
loren
Jr. Member ⚓︎
**


StatusCafe: ribose
iMood: ribose

View Profile WWW

First 1000 Members!spring 2023!Learning to swim!Joined 2022!
« Reply #6 on: January 17, 2024 @842.26 »

UPDATE: this is super broken :drat:

Quote from: Dev announcement on the XIVAPI discord (2023/12/30)
**Consider the lodestone endpoints as not working at all anymore**

While a fix has been deployed to the repo, it looks like there's an issue in the project itself to install dependencies using composer and I can't find how to fix this.

This is a good timing to remind you that many standalone parsers exist and we'd recommend you to use them even if the lodestone endpoint was working, because of common rate limitation issues.

but it's okay, i'm gonna try to write some new code to achieve the same result! 
it might take me some time to finish because i'll have to learn new things (more javascript? parsers??), but it's fun to learn new things so it's fine. stay tuned!
Logged
Pages: [1] Print 
« previous next »
 

Vaguely similar topics! (3)

GUIDE: Melon's Simple X3D World Tutorial

Started by MelooonBoard ✎ ∙ Art Crafting

Replies: 5
Views: 3766
Last post February 17, 2022 @637.75
by demonologi
What are some of your favorite 404 pages?

Started by Icey!Board ✁ ∙ Web Crafting

Replies: 14
Views: 3092
Last post April 13, 2024 @766.34
by oerrorpage
newsletters for dum-dums [not a tutorial, i'm the dum-dum]

Started by luluBoard ✑ ∙ Writers Corner

Replies: 3
Views: 1552
Last post June 27, 2022 @476.60
by Melooon

Melonking.Net © Always and ever was! SMF 2.0.19 | SMF © 2021, Simple Machines | Terms and Policies Forum Guide | Rules | RSS | WAP2


MelonLand Badges and Other Melon Sites!

MelonLand Project! Visit the MelonLand Forum! Support the Forum
Visit Melonking.Net! Visit the Gif Gallery! Pixel Sea TamaNOTchi