DEV Community

Stephen Hara
Stephen Hara

Posted on

No-Spoiler FF14 Progress Checks

As I've been playing the new FF14 expansion, I wanted to see if I could check my progress without spoilers. As it turns out, you can do it pretty easily with a bit of Javascript and JQuery!

First, open this page, which has a list of all the quests in the new expansion.

Second, open up the developer tools for your browser. You can right-click and find the option that way, or maybe the shortcut Ctrl+Shift+C works like it does for mine.

Next, open the console tab of the developer tools. This will open a little prompt you can use as a Javascript REPL!

We're going to build a JQuery selector to find the elements we want. JQuery is a Javascript library that allows you to filter HTML elements on a web page based on class, ID, element type, and more.

Ultimately, my approach uses the current quest name as the "search query". We can find the position of the quest name in the list of elements and divide that by the total number of quests in Dawntrail to get a percentage of our progress.

By inspecting the HTML, we can find a few clues to help us craft a good query. The first is that the quests all appear in HTML tables, so we can probably use tr and td as starting points.

The summary of the page mentions there are 100 quests, so to check how our query is coming along, we can make sure there are 100 elements in our result. Let's try this:
$('tr').size()

Not quite right, as this returns 111, meaning we captured 11 more elements than we expect. But looking at the tables, there's an extra row on each of them that might be causing problems.

Screenshot of the first sub-table of quests

To keep the header of each table from being captured, we can use a pseudo-class - 2 of them, in fact!

> $('tr:not(:first-child)').size()
Enter fullscreen mode Exit fullscreen mode

And that gives us 100! The pseudo-classes are :not and :first-child. :not takes another selector, including pseudo-classes, as an argument and filters them out of the results.

:first-child takes the first matching element of a group from the same parent. It's easier to understand with some examples, so I'd recommend checking the MDN page for more. https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child

Combined, tr:not(:first-child) means "when a node has multiple tr children, capture all of them except the first one". In terms of the quest table rows, this means we skip the header and only end up with the quest rows!

Within each tr row is a group of td cells: they include the quest name, the "type", level, quest giver, any unlocks, and any rewards.

Single quest row with boxes indicating the different cells

Quite convenient that once again, we only want to pick out the quest name - we can use :first-child again!

> $('tr:not(:first-child) > td:first-child').size()
Enter fullscreen mode Exit fullscreen mode

Again, we get 100, meaning we didn't lose anything with this addition. The last thing we need is to pick out the quest name. We can't do this directly from these td elements, but each element has an a tag.

Anchor tag for a single quest

We can capture these anchor elements in our selector:

> $('tr:not(:first-child) > td:first-child > a').size()
Enter fullscreen mode Exit fullscreen mode

And then we can use the JQuery function index(selector) to find the index of a matching selector. In this case, we'll use an attribute selector on the title attribute.

Putting this together, we can do something like:

> $('tr:not(:first-child) > td:first-child > a').index($('[title="A Saga in Stone"]'))
Enter fullscreen mode Exit fullscreen mode

This gives us 3, which is a classic off-by-one error. Since index looks at it like an array, we can add 1 to give us the position instead of the 0-based index.

> $('tr:not(:first-child) > td:first-child > a').index($('[title="A Saga in Stone"]')) + 1
4
Enter fullscreen mode Exit fullscreen mode

Meaning if you're on the quest "A Saga in Stone", you're on the 4th quest of the Dawntrail quest line!

Top comments (0)