-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.html
404 lines (361 loc) · 11.9 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
<title>Find root-affixes🍂 of word</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="container" class="w-100 h-70 flex-h">
<h1><a href="index.html" onclick="return onReset()">🥑</a> <span id="title"></span></h1>
<form id="form" class="w-100 flex" action="" onsubmit="return onSearch()">
<input id="word" type="search" name="word" autocomplete="off" width="100%" class="w-100"
placeholder="search word">
<input type="submit" value="🔍" />
</form>
<div class="rl-_8 flex">
<div id="tip"></div>
</div>
<div id="loader" class="loader wh-60px" hidden></div>
<div id="rootsAndAffixes" class="flex-1 rl-_8"></div>
<div class="flex">
<div class="flex-1"></div>
<div id="report" class="flex" hidden>
<a id="reportStatus" class="sp-_8" href="#report"></a>
<div id="reportLoader" class="loader wh-1em" hidden></div>
</div>
</div>
<details>
<summary>Log</summary>
<div id="log"></div>
</details>
</div>
<a href="https://github.com/excing/find-roots-of-word" target="_blank" class="abs-tr ic-github wh-80px"></a>
<script src="core.js"></script>
<script src="github.js"></script>
<script>
const CSS_CLASS_H_70 = "h-70"
const CSS_CLASS_H_MIN_100 = "h-min-100"
const TITLE = "Root-affixes 🍂"
const ISSUE_TITLE_SUFFIX = " -- Bad root-affix combinations"
const URL_INDEX = location.origin + location.pathname
const ID_LOADER = "loader"
const ID_REPORT_LOADER = "reportLoader"
const ID_REPORT = "report"
const ID_REPORT_STATUS = "reportStatus"
const REPORT_STATUS_AUTHING = "Github authentication in progress"
const REPORT_STATUS_GETTING = "Getting Github issue status"
const REPORT_STATUS_SENDING = "Sending"
const REPORT_STATUS_SEND_FAILED = "⚠️ Sending failed, please try again."
const REPORT_STATUS_BAD = "Bad root-affixes, report to GitHub"
const REPORT_STATUS_LOGIN = "Bad root-affixes, login to Github to report"
const REPORT_STATUS_SENT = "The bad root-affixes has been sent"
const REPORT_STATUS_FIXED = "The bad root-affixes has been fixed"
const REPORT_STATUS_RELOGIN = "⚠️ Login failed, please try again"
function onReset() {
reset()
return false
}
function onSearch() {
var wordEl = document.getElementById("word")
search(wordEl.value)
checkGithubIssue()
return false
}
function search(word) {
if ("" === word) {
reset()
return
}
visiable(ID_LOADER, true)
WordRootAffixes(word)
.then(data => {
if (data) {
return data
}
return []
})
.then(data => {
visiable(ID_LOADER, false)
return data
})
.then(data => {
setWordRootsAndAffixes(data)
pushStateHistory(word, data)
})
.catch(err => {
console.error(err)
visiable(ID_LOADER, false)
})
}
function setSearchWordInput(word) {
var wordEl = document.getElementById("word")
wordEl.value = word
wordEl.focus()
}
function setWordRootsAndAffixes(data) {
var containerEl = document.getElementById("container")
containerEl.classList.add(CSS_CLASS_H_MIN_100)
containerEl.classList.remove(CSS_CLASS_H_70)
var rootsAndAffixesEl = document.getElementById("rootsAndAffixes")
rootsAndAffixesEl.innerHTML = ""
var tipEl = document.getElementById("tip")
tipEl.innerHTML = ""
var logEl = document.getElementById("log")
logEl.innerHTML = ""
logEl.parentElement.hidden = false
var paths = data.paths
var combinationUnit = 1 == paths.length ? "combination" : "combinations"
addPToElement(
tipEl,
`Found ${paths.length} ${combinationUnit}, check the log for details (takes ${data.useTime}ms)`,
'red sp-_8 top-0',
)
if (null != data.exchange) {
let exchange = data.exchange
addPToElement(rootsAndAffixesEl, `[${exchange.lamme}]: ${exchange.desc}`, "bold top-1")
}
if (0 == paths.length) {
addPToElement(rootsAndAffixesEl, "🍉 No available root-affix combinations were found", "bold")
}
paths.forEach(element => {
addPToElement(rootsAndAffixesEl, element, "sp-1_2 top-1")
})
var allPath = data.all
allPath.forEach(path => {
addPToElement(logEl, path.value, "sp-_8")
})
}
function addPToElement(el, text, css = "") {
var p = document.createElement("p")
p.className = css
p.innerText = text
el.appendChild(p)
}
function pushStateHistory(word, data) {
let stateObj = { word: word, data: data, }
if ("" === word) {
history.replaceState(stateObj, TITLE, "index.html")
} else if (null == data) {
history.replaceState(stateObj, word + " —— " + TITLE, "?word=" + word)
} else {
history.pushState(stateObj, word + " —— " + TITLE, "?word=" + word)
}
}
function reset() {
visiable(ID_LOADER, false)
visiable(ID_REPORT, false)
setSearchWordInput("")
var containerEl = document.getElementById("container")
containerEl.classList.remove(CSS_CLASS_H_MIN_100)
containerEl.classList.add(CSS_CLASS_H_70)
var rootsAndAffixesEl = document.getElementById("rootsAndAffixes")
rootsAndAffixesEl.innerHTML = ""
var tipEl = document.getElementById("tip")
tipEl.innerHTML = ""
var logEl = document.getElementById("log")
logEl.innerHTML = ""
logEl.parentElement.hidden = true
addPToElement(tipEl, "Support global use of `Ctrl+v` or `Command+v`", "sp-_8 top-0 red")
pushStateHistory("", null)
}
// QA: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
// 必须要先获取焦点
function selectInput(input) {
input.focus()
input.setSelectionRange(0, input.value.length)
}
// QA: https://stackoverflow.com/a/2520670
function cancelSelect() {
document.activeElement.blur()
}
function accessGithubToken(code, state) {
visiable(ID_REPORT, true)
reportStatusAuthing()
AccessGithubToken(code, state, URL_INDEX)
.then(reportBadCombinations)
.catch(err => reportStatusLogin(REPORT_STATUS_RELOGIN))
}
function startGithubLogin() {
var urlParams = new URL(location).searchParams
if (!urlParams.has("word")) return
AuthorizeGithub(urlParams.get("word"), URL_INDEX)
}
function checkGithubLogin(thenFn) {
visiable(ID_REPORT, true)
reportStatusAuthing()
LoginGithub()
.then(thenFn)
.catch(startGithubLogin)
}
function checkGithubIssue(_404 = reportStatusBad) {
var wordEl = document.getElementById("word")
var word = wordEl.value
if (!word) {
visiable(ID_REPORT, false)
return
}
var title = joinIssueTitle(word)
visiable(ID_REPORT, true)
reportStatusGetting()
return GithubIssue(title)
.then(issue => {
if ("open" === issue.state) {
reportStatusSent(issue.html_url)
} else {
reportStatusFixed(issue.html_url)
}
})
.catch(err => {
_404()
})
}
function reportBadCombinations() {
var urlParams = new URL(location).searchParams
if (!urlParams.has("word")) return
var word = urlParams.get("word")
var result = WordHistoryResult(word)
var title = joinIssueTitle(word)
var label = result.label()
var content = result.markdown()
content += `\n\n## Test address`
content += `\n\n[${word} -- Find root-affixes🍂 of word](${location.href})`
reportStatusSending()
CreateGithubIssue(title, content, label)
.then(issue => reportStatusSent(issue.html_url))
.catch(reportStatusSendFailed)
}
function joinIssueTitle(word) {
return `${word}${ISSUE_TITLE_SUFFIX}`
}
function reportStatusLogin(text = REPORT_STATUS_LOGIN) {
visiable(ID_REPORT_LOADER, false)
innerText(ID_REPORT_STATUS, text)
onClick(ID_REPORT_STATUS, () => {
startGithubLogin()
return false
})
}
function reportStatusAuthing() {
visiable(ID_REPORT_LOADER, true)
innerText(ID_REPORT_STATUS, REPORT_STATUS_AUTHING)
onClick(ID_REPORT_STATUS, () => {
return false
})
}
function reportStatusGetting() {
visiable(ID_REPORT_LOADER, true)
innerText(ID_REPORT_STATUS, REPORT_STATUS_GETTING)
onClick(ID_REPORT_STATUS, () => {
return false
})
}
function reportStatusSending() {
visiable(ID_REPORT_LOADER, true)
innerText(ID_REPORT_STATUS, REPORT_STATUS_SENDING)
onClick(ID_REPORT_STATUS, () => {
return false
})
}
function reportStatusSendFailed() {
visiable(ID_REPORT_LOADER, false)
innerText(ID_REPORT_STATUS, REPORT_STATUS_SEND_FAILED)
onClick(ID_REPORT_STATUS, () => {
checkGithubLogin(reportBadCombinations)
return false
})
}
function reportStatusBad() {
visiable(ID_REPORT_LOADER, false)
innerText(ID_REPORT_STATUS, REPORT_STATUS_BAD)
onClick(ID_REPORT_STATUS, () => {
checkGithubLogin(reportBadCombinations)
return false
})
}
function reportStatusSent(url) {
visiable(ID_REPORT_LOADER, false)
innerText(ID_REPORT_STATUS, REPORT_STATUS_SENT)
onClick(ID_REPORT_STATUS, () => {
window.open(url)
return false
})
}
function reportStatusFixed(url) {
visiable(ID_REPORT_LOADER, false)
innerText(ID_REPORT_STATUS, REPORT_STATUS_FIXED)
onClick(ID_REPORT_STATUS, () => {
window.open(url)
return false
})
}
function onClick(id, fn) {
var el = document.getElementById(id)
el.onclick = fn
}
function innerText(id, text) {
var el = document.getElementById(id)
el.innerText = text
}
function visiable(id, visiable) {
var el = document.getElementById(id)
if (visiable) {
el.classList.remove("gone")
} else {
el.classList.add("gone")
}
el.hidden = !visiable
}
function init() {
innerText("title", TITLE)
var url = new URL(window.location)
var params = url.searchParams
if (params.has("word")) {
var word = params.get("word")
setSearchWordInput(word)
search(word)
checkGithubIssue()
} else if (params.has("code") && params.has("state")) {
var code = params.get("code")
var word = params.get("state")
setSearchWordInput(word)
search(word)
accessGithubToken(code, word)
} else {
reset()
}
}
window.onpopstate = function (e) {
var state = e.state
if (state && "" != state.word) {
setSearchWordInput(state.word)
setWordRootsAndAffixes(state.data)
checkGithubIssue()
} else if (state) {
reset()
}
}
document.onmouseover = function (e) {
if (e.target == document.getElementById("word")) {
selectInput(e.target)
} else {
cancelSelect()
}
}
// 参考:
// https://developer.mozilla.org/zh-CN/docs/Web/API/Element/paste_event
window.addEventListener("paste", (event) => {
let paste = (event.clipboardData || window.clipboardData).getData('text')
paste = paste.toLowerCase()
setSearchWordInput(paste)
event.preventDefault()
})
window.addEventListener("keydown", (event) => {
if ("Tab" == event.key && event.target == document.body) {
event.preventDefault()
selectInput(document.getElementById("word"))
}
})
init()
</script>
</body>
</html>