diff --git a/src/components/game.js b/src/components/game.js index 98b8baa..dd294a9 100644 --- a/src/components/game.js +++ b/src/components/game.js @@ -3,7 +3,17 @@ import { EventListeners } from './eventListeners' import Tippy from 'tippy.js' import 'tippy.js/dist/tippy.css' import { State } from './state' -import { getBaseUrl, getClassName, getSign, optionally, reload, url, urlParams, writeToClipboard } from './util' +import { + getBaseUrl, + getClassName, + getDateId, + getSign, + optionally, + reload, + url, + urlParams, + writeToClipboard +} from './util' import { Cell } from './cell' import { Cache } from './cache' import { Dictionary } from './dictionary' @@ -11,6 +21,8 @@ import { Word } from './word' const $expand = document.getElementById('expand') const $footer = document.getElementById('footer') +const $hiddenWords = document.getElementById('hidden-words') +const $hiddenWordsList = document.getElementById('hidden-words-list') const $hint = document.getElementById('hint') const $includeProfanity = document.getElementById('include-profanity') const $includeSolution = document.getElementById('include-solution') @@ -59,9 +71,10 @@ export class Game { const params = new URLSearchParams(url.search) params.set(Grid.Params.Id.key, crypto.randomUUID().split('-')[0]) - $new.href = `?${params.toString()}` - $path.href = `?${Grid.Params.Id.key}=${this.#configuration.id}` + + params.set(Grid.Params.Id.key, this.#configuration.id) + $path.href = `?${params.toString()}` $path.textContent = this.#configuration.id this.#eventListeners.add([ @@ -101,6 +114,7 @@ export class Game { await this.#dictionary.load(Dictionary.Sources.Default) this.#grid.setup() this.update() + this.#updateHiddenWords() const state = this.#getState() @@ -247,6 +261,38 @@ export class Game { $includeSolution.checked = state.shareUrl.solution } + #updateHiddenWords () { + const isToday = this.#configuration.id === Grid.DefaultId + if (isToday) { + // For the current day, just display a link to the previous day's words + const date = new Date() + date.setDate(date.getDate() - 1) + const previousId = getDateId(date) + const a = document.createElement('a') + const params = new URLSearchParams(url.search) + params.set(Grid.Params.Id.key, previousId) + a.href = `?${params.toString()}#hidden-words` + a.target = '_blank' + a.textContent = "Yesterday's Hidden Words" + $hiddenWords.replaceChildren(a) + } else { + if (url.hash.includes('hidden-words')) { + $hiddenWords.querySelector('details').setAttribute('open', '') + } + const state = this.#grid.getState() + state.configuration.words.forEach((word) => { + const li = document.createElement('li') + const a = document.createElement('a') + a.href = Game.getWordUrl(word) + a.target = '_blank' + a.textContent = word.toString() + a.title = 'See definition' + li.append(a) + $hiddenWordsList.append(li) + }) + } + } + #updateHint () { $hint.classList.toggle(Game.ClassNames.Disabled, !this.#grid.hasHint()) } @@ -366,7 +412,7 @@ export class Game { $index.textContent = `${length - index}.` const $word = document.createElement('a') $word.classList.add(Game.ClassNames.Word, getClassName(Game.ClassNames.Word, 'match', data.match)) - $word.href = 'https://en.wiktionary.org/wiki/' + word.content + $word.href = Game.getWordUrl(word.content) $word.target = '_blank' $word.textContent = word.content $word.title = 'See definition' @@ -412,6 +458,10 @@ export class Game { return $li } + static getWordUrl (word) { + return 'https://en.wiktionary.org/wiki/' + encodeURIComponent(word) + } + static CacheKey = 'game' static ClassNames = Object.freeze({ diff --git a/src/components/grid.js b/src/components/grid.js index 08593b4..e4beadb 100644 --- a/src/components/grid.js +++ b/src/components/grid.js @@ -8,7 +8,7 @@ import { arrayEquals, arrayIncludes, cyrb53, - getClassName, + getClassName, getDateId, history, optionally, reverseString, sortNumerically, url, @@ -791,14 +791,7 @@ export class Grid { static Name = 'grid' static ClassNames = Object.freeze({ Loading: getClassName(Grid.Name, 'loading') }) static DateRegex = /^\d{4}-\d{2}-\d{2}$/ - static DefaultId = (() => { - // The ID for the daily puzzle - const date = new Date() - const year = date.getFullYear() - const month = (date.getMonth() + 1).toString().padStart(2, '0') - const day = date.getDate().toString().padStart(2, '0') - return `${year}-${month}-${day}` - })() + static DefaultId = getDateId(new Date()) static Events = Object.freeze({ Selection: getClassName(Grid.Name, 'selection'), diff --git a/src/components/util.js b/src/components/util.js index f414d8c..e60c4a0 100644 --- a/src/components/util.js +++ b/src/components/util.js @@ -49,6 +49,13 @@ export function getClassName (...parts) { return parts.join('-') } +export function getDateId (date) { + const year = date.getFullYear() + const month = (date.getMonth() + 1).toString().padStart(2, '0') + const day = date.getDate().toString().padStart(2, '0') + return `${year}-${month}-${day}` +} + export function getIndexesUnique (rand, array, max) { const available = Object.keys(array) if (max > available.length) { diff --git a/src/index.html b/src/index.html index 393a98f..f53d58c 100644 --- a/src/index.html +++ b/src/index.html @@ -330,6 +330,12 @@

Settings

+
+
+ Show Hidden Words (Spoiler) + +
+
diff --git a/src/styles.css b/src/styles.css index a42a307..a160781 100644 --- a/src/styles.css +++ b/src/styles.css @@ -226,6 +226,17 @@ p.center { width: 100%; } +#hidden-words-list { + list-style: inside decimal; +} + +#hidden-words-list a { + color: #d2d3cd; + font-weight: normal; + text-decoration: none; + text-transform: uppercase; +} + #letter-points .letters { text-transform: uppercase; } @@ -348,9 +359,11 @@ p.center { } .drawer h3, -.drawer summary { +.drawer summary, +.drawer a { color: white; font-size: 1em; + font-weight: bold; margin: 0 0 0.5em 0; }