OpenLab-NLP commited on
Commit
12134bb
ยท
verified ยท
1 Parent(s): c37a8db

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +105 -33
index.html CHANGED
@@ -11,6 +11,7 @@
11
  --primary-color: #5d5b54; /* ์ง„ํ•œ ํšŒ๊ฐˆ์ƒ‰ (ํ…์ŠคํŠธ) */
12
  --accent-color: #d4a373; /* ํฌ์ธํŠธ ์ปฌ๋Ÿฌ (๋ฒ ์ด์ง€ ๋ธŒ๋ผ์šด) */
13
  --border-color: #e0ddd5;
 
14
  }
15
 
16
  body {
@@ -35,13 +36,15 @@
35
  }
36
  input[type="text"] {
37
  flex: 1;
38
- padding: 12px 20px;
39
  border: 1px solid var(--border-color);
40
  border-radius: 30px;
41
  outline: none;
42
  background-color: var(--card-bg);
 
 
43
  }
44
- input[type="text"]:focus { border-color: var(--accent-color); }
45
 
46
  /* ์นดํ…Œ๊ณ ๋ฆฌ ๋ฒ„ํŠผ */
47
  .filter-container {
@@ -50,7 +53,7 @@
50
  justify-content: center;
51
  gap: 8px;
52
  margin-bottom: 40px;
53
- max-width: 800px;
54
  margin-left: auto;
55
  margin-right: auto;
56
  }
@@ -72,48 +75,53 @@
72
 
73
  /* ํ…Œ์ด๋ธ” ๋””์ž์ธ */
74
  .table-wrapper {
75
- max-width: 900px;
76
  margin: 0 auto;
77
  background: var(--card-bg);
78
  border-radius: 15px;
79
  overflow: hidden;
80
  box-shadow: 0 10px 30px rgba(0,0,0,0.05);
81
  }
82
- table { width: 100%; border-collapse: collapse; }
83
- th, td { padding: 15px 20px; text-align: left; border-bottom: 1px solid var(--bg-color); }
84
  th { background: #f1eee6; font-weight: 600; font-size: 0.9rem; color: #777; }
85
  tr:last-child td { border-bottom: none; }
86
- tr:hover { background-color: #fafafa; }
87
 
88
  .word-cell { font-weight: bold; color: var(--accent-color); font-size: 1.1rem; }
89
  .path-cell { font-size: 0.75rem; color: #bbb; }
 
 
 
 
90
  </style>
91
  </head>
92
  <body>
93
 
94
  <header>
95
  <h1>HUIUCL</h1>
96
- <div class="sub-title">์ธ๊ณต์–ด ํ›„์ด์šฐํด ์˜จ๋ผ์ธ ์‚ฌ์ „ ์•„์นด์ด๋ธŒ</div>
97
  </header>
98
 
99
  <div class="search-container">
100
- <input type="text" id="searchInput" placeholder="๋‹จ์–ด ๋˜๋Š” ๋œป์„ ๊ฒ€์ƒ‰ํ•˜์„ธ์š”..." onkeyup="filterData()">
101
  </div>
102
 
103
  <div class="filter-container" id="categoryButtons">
104
- <button onclick="changeCategory('๋ชจ๋‘')" id="btn-all" class="active">๋ชจ๋‘ ๋ณด๊ธฐ</button>
105
  </div>
106
 
107
  <div class="table-wrapper">
108
  <table>
109
  <thead>
110
  <tr>
111
- <th style="width: 30%;">๋‹จ์–ด</th>
112
- <th style="width: 40%;">์˜๋ฏธ</th>
113
  <th style="width: 30%;">๋ถ„๋ฅ˜</th>
114
  </tr>
115
  </thead>
116
- <tbody id="dictBody"></tbody>
 
 
117
  </table>
118
  </div>
119
 
@@ -128,25 +136,36 @@
128
  conlangData = data;
129
  initButtons();
130
  renderTable();
 
 
 
 
131
  });
132
 
133
  function initButtons() {
134
  const container = document.getElementById('categoryButtons');
 
135
  Object.keys(conlangData).forEach(key => {
136
  if (key === "์„ค์ •") return;
137
  const btn = document.createElement('button');
138
  btn.innerText = key;
139
- btn.onclick = (e) => {
140
- document.querySelectorAll('button').forEach(b => b.classList.remove('active'));
141
- e.target.classList.add('active');
142
- currentCategory = key;
143
- renderTable();
144
- };
145
  container.appendChild(btn);
146
  });
147
  }
148
 
149
- // ๊ฒ€์ƒ‰ ๋ฐ ํ•„ํ„ฐ๋ง ํ•ต์‹ฌ ํ•จ์ˆ˜
 
 
 
 
 
 
 
 
 
 
 
150
  function renderTable() {
151
  const body = document.getElementById('dictBody');
152
  const searchTerm = document.getElementById('searchInput').value.toLowerCase();
@@ -159,37 +178,90 @@
159
  targets.forEach(cat => {
160
  traverse(conlangData[cat], cat, searchTerm);
161
  });
 
 
 
 
162
  }
163
 
 
 
 
 
 
 
164
  function traverse(obj, path, search) {
165
  for (const key in obj) {
166
- if (typeof obj[key] === 'string' || obj[key].hasOwnProperty('๋œป')) {
 
 
 
 
 
167
  const word = key;
168
- const meaning = typeof obj[key] === 'string' ? obj[key] : obj[key].๋œป;
169
 
170
- // ๊ฒ€์ƒ‰์–ด ํ•„ํ„ฐ๋ง
171
  if (word.toLowerCase().includes(search) || meaning.toLowerCase().includes(search)) {
172
- addRow(word, meaning, path);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
- } else if (typeof obj[key] === 'object' && key !== "๋ณ€ํ˜•") {
175
- traverse(obj[key], `${path} > ${key}`, search);
176
  }
177
  }
178
  }
179
 
180
- function addRow(word, meaning, path) {
181
  const body = document.getElementById('dictBody');
182
  const row = body.insertRow();
 
 
183
  row.innerHTML = `
184
- <td class="word-cell">${word}</td>
185
- <td>${meaning}</td>
 
 
186
  <td class="path-cell">${path}</td>
187
  `;
188
  }
189
-
190
- function filterData() {
191
- renderTable();
192
- }
193
  </script>
194
 
195
  </body>
 
11
  --primary-color: #5d5b54; /* ์ง„ํ•œ ํšŒ๊ฐˆ์ƒ‰ (ํ…์ŠคํŠธ) */
12
  --accent-color: #d4a373; /* ํฌ์ธํŠธ ์ปฌ๋Ÿฌ (๋ฒ ์ด์ง€ ๋ธŒ๋ผ์šด) */
13
  --border-color: #e0ddd5;
14
+ --variation-bg: #faf9f6; /* ๋ณ€ํ˜• ๋‹จ์–ด ๋ฐฐ๊ฒฝ์ƒ‰ */
15
  }
16
 
17
  body {
 
36
  }
37
  input[type="text"] {
38
  flex: 1;
39
+ padding: 12px 24px;
40
  border: 1px solid var(--border-color);
41
  border-radius: 30px;
42
  outline: none;
43
  background-color: var(--card-bg);
44
+ font-size: 1rem;
45
+ box-shadow: 0 2px 5px rgba(0,0,0,0.02);
46
  }
47
+ input[type="text"]:focus { border-color: var(--accent-color); box-shadow: 0 2px 10px rgba(212, 163, 115, 0.2); }
48
 
49
  /* ์นดํ…Œ๊ณ ๋ฆฌ ๋ฒ„ํŠผ */
50
  .filter-container {
 
53
  justify-content: center;
54
  gap: 8px;
55
  margin-bottom: 40px;
56
+ max-width: 900px;
57
  margin-left: auto;
58
  margin-right: auto;
59
  }
 
75
 
76
  /* ํ…Œ์ด๋ธ” ๋””์ž์ธ */
77
  .table-wrapper {
78
+ max-width: 1000px;
79
  margin: 0 auto;
80
  background: var(--card-bg);
81
  border-radius: 15px;
82
  overflow: hidden;
83
  box-shadow: 0 10px 30px rgba(0,0,0,0.05);
84
  }
85
+ table { width: 100%; border-collapse: collapse; table-layout: fixed; }
86
+ th, td { padding: 15px 20px; text-align: left; border-bottom: 1px solid var(--bg-color); overflow: hidden; text-overflow: ellipsis; }
87
  th { background: #f1eee6; font-weight: 600; font-size: 0.9rem; color: #777; }
88
  tr:last-child td { border-bottom: none; }
 
89
 
90
  .word-cell { font-weight: bold; color: var(--accent-color); font-size: 1.1rem; }
91
  .path-cell { font-size: 0.75rem; color: #bbb; }
92
+
93
+ /* ๋ณ€ํ˜•(Variation) ํ–‰ ์Šคํƒ€์ผ */
94
+ .variation-row { background-color: var(--variation-bg); }
95
+ .variation-icon { color: #ccc; margin-right: 8px; font-weight: normal; }
96
  </style>
97
  </head>
98
  <body>
99
 
100
  <header>
101
  <h1>HUIUCL</h1>
102
+ <div class="sub-title">์ธ๊ณต์–ด ํ›„์ด์šฐํด ์˜จ๋ผ์ธ ์‚ฌ์ „</div>
103
  </header>
104
 
105
  <div class="search-container">
106
+ <input type="text" id="searchInput" placeholder="์ฐพ๊ณ  ์‹ถ์€ ๋‹จ์–ด๋‚˜ ๋œป์„ ์ž…๋ ฅํ•˜์„ธ์š”..." onkeyup="filterData()">
107
  </div>
108
 
109
  <div class="filter-container" id="categoryButtons">
110
+ <button onclick="changeCategory('๋ชจ๋‘', this)" class="active">๋ชจ๋‘ ๋ณด๊ธฐ</button>
111
  </div>
112
 
113
  <div class="table-wrapper">
114
  <table>
115
  <thead>
116
  <tr>
117
+ <th style="width: 35%;">๋‹จ์–ด (Huiucl)</th>
118
+ <th style="width: 35%;">์˜๋ฏธ (Korean)</th>
119
  <th style="width: 30%;">๋ถ„๋ฅ˜</th>
120
  </tr>
121
  </thead>
122
+ <tbody id="dictBody">
123
+ <tr><td colspan="3" style="text-align:center; padding:50px; color:#ccc;">๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค...</td></tr>
124
+ </tbody>
125
  </table>
126
  </div>
127
 
 
136
  conlangData = data;
137
  initButtons();
138
  renderTable();
139
+ })
140
+ .catch(err => {
141
+ console.error("Error loading JSON:", err);
142
+ document.getElementById('dictBody').innerHTML = '<tr><td colspan="3" style="text-align:center; color:red; padding:50px;">๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹คํŒจ (CORS ์ •์ฑ… ํ˜น์€ ํŒŒ์ผ๋ช…์„ ํ™•์ธํ•˜์„ธ์š”)</td></tr>';
143
  });
144
 
145
  function initButtons() {
146
  const container = document.getElementById('categoryButtons');
147
+ // '์„ค์ •'์„ ์ œ์™ธํ•œ ์ตœ์ƒ์œ„ ํ‚ค๋“ค๋กœ ๋ฒ„ํŠผ ์ƒ์„ฑ
148
  Object.keys(conlangData).forEach(key => {
149
  if (key === "์„ค์ •") return;
150
  const btn = document.createElement('button');
151
  btn.innerText = key;
152
+ btn.onclick = (e) => changeCategory(key, e.target);
 
 
 
 
 
153
  container.appendChild(btn);
154
  });
155
  }
156
 
157
+ function changeCategory(key, target) {
158
+ document.querySelectorAll('button').forEach(b => b.classList.remove('active'));
159
+ target.classList.add('active');
160
+ currentCategory = key;
161
+ renderTable();
162
+ }
163
+
164
+ function filterData() {
165
+ renderTable();
166
+ }
167
+
168
+ // ํ…Œ์ด๋ธ” ๋ Œ๋”๋ง ํ•จ์ˆ˜
169
  function renderTable() {
170
  const body = document.getElementById('dictBody');
171
  const searchTerm = document.getElementById('searchInput').value.toLowerCase();
 
178
  targets.forEach(cat => {
179
  traverse(conlangData[cat], cat, searchTerm);
180
  });
181
+
182
+ if (body.innerHTML === '') {
183
+ body.innerHTML = '<tr><td colspan="3" style="text-align:center; padding:50px; color:#999;">๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.</td></tr>';
184
+ }
185
  }
186
 
187
+ /**
188
+ * ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜๋Š” ํ•จ์ˆ˜
189
+ * @param {Object} obj - ํƒ์ƒ‰ํ•  ๊ฐ์ฒด
190
+ * @param {String} path - ํ˜„์žฌ ์นดํ…Œ๊ณ ๋ฆฌ ๊ฒฝ๋กœ
191
+ * @param {String} search - ๊ฒ€์ƒ‰์–ด
192
+ */
193
  function traverse(obj, path, search) {
194
  for (const key in obj) {
195
+ if (key === "์„ค์ •" || key === "๋ณ€ํ˜•") continue;
196
+
197
+ const item = obj[key];
198
+
199
+ // Case A: ์ง์ ‘ "๋œป"์„ ๊ฐ€์ง„ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ
200
+ if (item && typeof item === 'object' && item.hasOwnProperty('๋œป')) {
201
  const word = key;
202
+ const meaning = item.๋œป;
203
 
 
204
  if (word.toLowerCase().includes(search) || meaning.toLowerCase().includes(search)) {
205
+ addRow(word, meaning, path, false);
206
+ }
207
+
208
+ // ๋‹จ์–ด ๋‚ด๋ถ€์— ๋™์ผํ•œ ์ด๋ฆ„์˜ '๋ณ€ํ˜• ๊ฐ์ฒด'๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ (์˜ˆ: sachi ์•ˆ์˜ sachi)
209
+ if (item[key] && typeof item[key] === 'object') {
210
+ processVariations(item[key], `${path} > ${key}`, search);
211
+ }
212
+ }
213
+ // Case B: ๊ฐ’์ด ๋‹จ์ˆœ ๋ฌธ์ž์—ด์ธ ๊ฒฝ์šฐ (๋‹จ์–ด: ๋œป)
214
+ else if (typeof item === 'string') {
215
+ if (key.toLowerCase().includes(search) || item.toLowerCase().includes(search)) {
216
+ addRow(key, item, path, false);
217
+ }
218
+ }
219
+ // Case C: ํ•˜์œ„ ์นดํ…Œ๊ณ ๋ฆฌ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ (๋œป์ด ์—†๊ณ  ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์„ ํฌํ•จ)
220
+ else if (typeof item === 'object') {
221
+ traverse(item, `${path} > ${key}`, search);
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * ๋ณ€ํ˜•(Variation) ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜ (์ค‘์ฒฉ๋œ li henna ๋“ฑ ๋Œ€์‘)
228
+ */
229
+ function processVariations(vObj, path, search) {
230
+ for (const vKey in vObj) {
231
+ const vVal = vObj[vKey];
232
+
233
+ if (typeof vVal === 'string') {
234
+ if (vKey.toLowerCase().includes(search) || vVal.toLowerCase().includes(search)) {
235
+ addRow(vKey, vVal, path, true);
236
+ }
237
+ } else if (vVal && typeof vVal === 'object') {
238
+ // ๋ณ€ํ˜• ๋‚ด๋ถ€์— ๋˜ ๋œป๊ณผ ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ (์˜ˆ: li henna)
239
+ if (vVal.๋œป) {
240
+ if (vKey.toLowerCase().includes(search) || vVal.๋œป.toLowerCase().includes(search)) {
241
+ addRow(vKey, vVal.๋œป, path, true);
242
+ }
243
+ // ๋” ๊นŠ์€ ๋ณ€ํ˜•์ด ์žˆ๋‹ค๋ฉด ์žฌ๊ท€ ํ˜ธ์ถœ
244
+ if (vVal[vKey]) processVariations(vVal[vKey], `${path} > ${vKey}`, search);
245
+ } else {
246
+ processVariations(vVal, path, search);
247
  }
 
 
248
  }
249
  }
250
  }
251
 
252
+ function addRow(word, meaning, path, isVariation) {
253
  const body = document.getElementById('dictBody');
254
  const row = body.insertRow();
255
+ if (isVariation) row.className = 'variation-row';
256
+
257
  row.innerHTML = `
258
+ <td class="word-cell" style="${isVariation ? 'padding-left: 40px; color: #999; font-size: 0.95rem;' : ''}">
259
+ ${isVariation ? '<span class="variation-icon">โ†ณ</span>' : ''}${word}
260
+ </td>
261
+ <td style="${isVariation ? 'color: #777;' : ''}">${meaning}</td>
262
  <td class="path-cell">${path}</td>
263
  `;
264
  }
 
 
 
 
265
  </script>
266
 
267
  </body>