Skip to content

Commit 519cb2a

Browse files
committed
refactor: removed dependency on jquery
1 parent a8715ad commit 519cb2a

File tree

6 files changed

+63
-50
lines changed

6 files changed

+63
-50
lines changed

public/3rd-party/jquery/jquery-3.7.1.min.js

Lines changed: 0 additions & 2 deletions
This file was deleted.

public/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ <h1 id="current-word" class="display-3 fw-bold mb-0">単語</h1>
176176
</footer>
177177

178178
<script src="3rd-party/bootstrap/bootstrap.bundle.min.js"></script>
179-
<script src="3rd-party/jquery/jquery-3.7.1.min.js"></script>
180179
<script src="js/app.js" type="module" ></script>
181180
<script> navigator.serviceWorker?.register('service-worker.js')</script>
182181

public/js/app.js

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,24 @@ class LetMatrixVocabApp {
3333
async init() {
3434
// Check for Web Serial API support
3535
if (!('serial' in navigator)) {
36-
$('#unsupportedBrowserWarning').show();
37-
$('#connect-btn-1, #connect-btn-2').prop('disabled', true);
36+
document.getElementById('unsupportedBrowserWarning')
37+
.style.display = 'block';
38+
document.querySelectorAll('#connect-btn-1, #connect-btn-2')
39+
.forEach(btn => btn.disabled = true);
3840
}
3941

4042
// Populate the word source dropdown
41-
const $select = $('#word-source-select');
43+
const select = document.getElementById('word-source-select');
4244
for (const s of getSources()) {
43-
$select.append(
44-
$(`<option value="${s.value}">${s.title}</option>`)
45-
);
45+
const option = document.createElement('option');
46+
option.value = s.value;
47+
option.textContent = s.title;
48+
select.appendChild(option);
4649
}
4750

4851
// Set initial state from DOM
49-
this.waitPeriod = $('#delay-input').val();
50-
this.autoUpdate = $('#auto-mode-switch').is(':checked');
52+
this.waitPeriod = document.getElementById('delay-input').value;
53+
this.autoUpdate = document.getElementById('auto-mode-switch').checked;
5154

5255
await this.loadWord('単語');
5356

@@ -59,19 +62,27 @@ class LetMatrixVocabApp {
5962
bindEvents() {
6063
// Connect Buttons
6164
this.modules.forEach((_, index) => {
62-
$(`#connect-btn-${index + 1}`).on('click', () => this.handleConnectClick(index));
65+
document.getElementById(`connect-btn-${index + 1}`)
66+
.addEventListener('click', () => this.handleConnectClick(index));
6367
});
6468

6569
// Control Inputs
66-
$('#swap-ports-btn').on('click', () => this.handleSwapPorts());
67-
$('#new-word-btn').on('click', () => this.handleNewWord());
68-
$('#auto-mode-switch').on('change', (e) => this.handleAutoModeChange(e));
69-
$('#delay-input').on('change', (e) => this.handleDelayChange(e));
70-
$('#word-source-select').on('change', (e) => this.handleSourceChange(e));
70+
document.getElementById('swap-ports-btn')
71+
.addEventListener('click', () => this.handleSwapPorts());
72+
document.getElementById('new-word-btn')
73+
.addEventListener('click', () => this.handleNewWord());
74+
document.getElementById('auto-mode-switch')
75+
.addEventListener('change', (e) => this.handleAutoModeChange(e));
76+
document.getElementById('delay-input')
77+
.addEventListener('change', (e) => this.handleDelayChange(e));
78+
document.getElementById('word-source-select')
79+
.addEventListener('change', (e) => this.handleSourceChange(e));
7180

7281
// Light/Dark Mode
73-
$('[data-bs-theme-value]').on('click', (e) => {
74-
$('html').attr('data-bs-theme', $(e.target).attr('data-bs-theme-value'));
82+
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
83+
element.addEventListener('click', (e) => {
84+
document.documentElement.setAttribute('data-bs-theme', e.target.getAttribute('data-bs-theme-value'));
85+
});
7586
});
7687
}
7788

@@ -89,7 +100,7 @@ class LetMatrixVocabApp {
89100
const ver = await module.getFirmwareVersion();
90101
if (ver) {
91102
this.statusConnected(index, ver);
92-
$(buttonSelector).prop('disabled', true);
103+
document.querySelector(buttonSelector).disabled = true;
93104
await buffer.clear();
94105
} else {
95106
throw new Error('No firmware version received.');
@@ -106,10 +117,10 @@ class LetMatrixVocabApp {
106117
await this.display.forceTx();
107118

108119
// Swap port status HTML
109-
const status1 = $('#status-display-1').html();
110-
const status2 = $('#status-display-2').html();
111-
$('#status-display-1').html(status2);
112-
$('#status-display-2').html(status1);
120+
const status1 = document.getElementById('status-display-1').innerHTML;
121+
const status2 = document.getElementById('status-display-2').innerHTML;
122+
document.getElementById('status-display-1').innerHTML = status2;
123+
document.getElementById('status-display-2').innerHTML = status1;
113124
}
114125

115126
async handleNewWord() {
@@ -119,7 +130,7 @@ class LetMatrixVocabApp {
119130
this.timeLastUpdated = Date.now(); // Reset timer on manual change
120131
} catch (error) {
121132
console.error("Failed to fetch or render new word:", error);
122-
$('#current-word').html("Error");
133+
document.getElementById('current-word').innerHTML = "Error";
123134
}
124135
}
125136

@@ -134,7 +145,7 @@ class LetMatrixVocabApp {
134145
}
135146

136147
handleSourceChange(e) {
137-
const selectedValue = $(e.currentTarget).val();
148+
const selectedValue = e.currentTarget.value;
138149
this.wordSource = getSources().find(s => s.value === selectedValue);
139150
this.wordSource ??= getSources()[0];
140151
}
@@ -143,29 +154,30 @@ class LetMatrixVocabApp {
143154

144155
async loadWord(word) {
145156
this.wordMarquee.load(word);
146-
$('#current-word').html(word);
147-
$('#jisho-link').prop('href', `https://jisho.org/search/${word}`);
157+
document.getElementById('current-word').innerHTML = word;
158+
document.getElementById('jisho-link')
159+
.setAttribute('href', `https://jisho.org/search/${word}`);
148160
}
149161

150162
statusConnected(index, ver) {
151-
$(`#status-display-${index + 1}`).html(`
163+
document.getElementById(`status-display-${index + 1}`).innerHTML = `
152164
<span class="status-indicator status-connected"></span>
153165
<span class="text-muted">Connected! Firmware Ver. ${ver.major}.${ver.minor}.${ver.patch}</span>
154-
`);
166+
`;
155167
}
156168

157169
statusConnecting(index) {
158-
$(`#status-display-${index + 1}`).html(`
170+
document.getElementById(`status-display-${index + 1}`).innerHTML = `
159171
<span class="status-indicator status-disconnected"></span>
160172
<span class="text-muted">Connecting...</span>
161-
`);
173+
`;
162174
}
163175

164176
statusFail(index) {
165-
$(`#status-display-${index + 1}`).html(`
177+
document.getElementById(`status-display-${index + 1}`).innerHTML = `
166178
<span class="status-indicator status-disconnected"></span>
167179
<span class="text-muted">Failed to connect</span>
168-
`);
180+
`;
169181
}
170182

171183
startUpdateLoop() {
@@ -175,8 +187,9 @@ class LetMatrixVocabApp {
175187
const elapsed = (Date.now() - this.timeLastUpdated) / 1000;
176188
let timeLeftSec = this.waitPeriod - elapsed;
177189
let timeLeftShown = Math.max(0, Math.round(timeLeftSec));
178-
179-
$('#countdown-text').html(`New word in: ${timeLeftShown}s`);
190+
191+
document.getElementById('countdown-text').innerHTML =
192+
`New word in: ${timeLeftShown}s`;
180193

181194
if (timeLeftSec < 0.5) {
182195
// This method also resets the timer
@@ -196,7 +209,7 @@ class LetMatrixVocabApp {
196209
}
197210

198211
// --- Run App ---
199-
$(async function() {
212+
document.addEventListener('DOMContentLoaded', async () => {
200213
const app = new LetMatrixVocabApp();
201214
await app.init();
202215
});

public/js/data-sources.js

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { fetchJson } from "./util.js";
2+
13
class OfflineJlptSource {
24
static async init() {
3-
OfflineJlptSource.#words = await $.getJSON(
5+
OfflineJlptSource.#words = await fetchJson(
46
'datasets/jlpt-words-by-level.json'
57
);
68
}
@@ -25,7 +27,7 @@ class OfflineJlptSource {
2527

2628
class OfflineWikipediaSource {
2729
static async init() {
28-
OfflineWikipediaSource.#words = await $.getJSON(
30+
OfflineWikipediaSource.#words = await fetchJson(
2931
'datasets/jawiki-2022-08-29.json'
3032
);
3133
}
@@ -50,22 +52,15 @@ class OnlineJlptSource {
5052
static async init() {
5153
const url = 'https://jlpt-vocab-api.vercel.app/api/words/random';
5254

53-
OnlineJlptSource.#cache = (async () => {
54-
const res = await fetch(url);
55-
if (!res.ok) {
56-
throw new Error(`Response status: ${res.status}`);
57-
} else {
58-
return await res.json();
59-
}
60-
})();
55+
OnlineJlptSource.#cache = (async () => fetchJson(url))();
6156

6257
await OnlineJlptSource.#cache;
6358
}
6459

6560
static async getEntry() {
6661
if (!this.#cache) await this.init();
6762

68-
// getWord() may be called before init()/getWord() returns
63+
// getEntry() may be called before init()/getWord() returns
6964
const entry = await this.#cache;
7065
this.#cache = null;
7166
this.init();

public/js/util.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,12 @@ export function toGrayscaleMatrix(img) {
5757

5858
return matrix;
5959
}
60+
61+
export async function fetchJson(url) {
62+
const response = await fetch(url);
63+
if (!response.ok) {
64+
throw new Error(`HTTP error! status: ${response.status}`);
65+
} else {
66+
return await response.json();
67+
}
68+
}

public/service-worker.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const CACHE_VERSION = 'v1';
1+
const CACHE_VERSION = 'v2';
22
const CACHE_NAME = `led-vocab-${CACHE_VERSION}`;
33

44
const ASSETS_TO_CACHE = [
@@ -14,7 +14,6 @@ const ASSETS_TO_CACHE = [
1414
'3rd-party/bootstrap-icons/bootstrap-icons.min.css',
1515
'3rd-party/bootstrap-icons/fonts/bootstrap-icons.woff',
1616
'3rd-party/bootstrap-icons/fonts/bootstrap-icons.woff2',
17-
'3rd-party/jquery/jquery-3.7.1.min.js',
1817
'fonts/JF-Dot-jiskan16-1990.woff2',
1918
'js/app.js',
2019
'js/constants.js',

0 commit comments

Comments
 (0)