Utilisateur:Yopyop456/Brouillon/cnchar
Apparence
Cette page est un brouillon appartenant à Yopyop456
Conseils de rédaction
- → N'hésitez pas à publier sur le brouillon un texte inachevé et à le modifier autant que vous le souhaitez.
- → Pour enregistrer vos modifications au brouillon, il est nécessaire de cliquer sur le bouton bleu : « Publier les modifications ». Il n'y a pas d'enregistrement automatique.
Si votre but est de publier un nouvel article, votre brouillon doit respecter les points suivants :
- Respectez le droit d'auteur en créant un texte spécialement pour Wikipédia en français (pas de copier-coller venu d'ailleurs).
- Indiquez les éléments démontrant la notoriété du sujet (aide).
- Liez chaque fait présenté à une source de qualité (quelles sources – comment les insérer).
- Utilisez un ton neutre, qui ne soit ni orienté ni publicitaire (aide).
- Veillez également à structurer votre article, de manière à ce qu'il soit conforme aux autres pages de l'encyclopédie (structurer – mettre en page).
- → Si ces points sont respectés, pour transformer votre brouillon en article, utilisez le bouton « publier le brouillon » en haut à droite. Votre brouillon sera alors transféré dans l'espace encyclopédique.
/*
chinesepod
chairmansbao
https://www.chinesepod.com/api/v1/lessons/get-lesson/?lessonId=6030
*/
class cnDict{
static data = {};
static settings = undefined;
static searchIndex = (str, name='hsk')=>{
return this.data[name].value[this.data[name].key.indexOf(str)];
}
static searchField(str, name='hsk', field='level'){
let ret = []
this.data[name].value.forEach(element => {
if(element[field] == str) ret.push(element)
});
return ret
}
}
async function start2(){
await loadExternal()
await loadDict()
handleModal()
handleDisplay()
}
async function loadExternal(){
window.process = {env:{NODE_ENV: 'production'}}
window._ ??= await import('/js/0utils/utils3.mjs')
// window._ ??= await import('./utils3.mjs')
window.VirtualCore ??= await import('./virtual-core/dist/esm/index.js')
if(!document.querySelector('#dict_table_style')){
let css = `
.field_simplified,
.field_traditional,
.field_pinyin,
.field_pinyin2,
.field_category_fr,
.field_definition_fr,
.field_example,
.field_id,
.field_level,
.field_list,
.field_checkbox {
display: none;
}
.show_simplified .field_simplified,
.show_traditional .field_traditional,
.show_pinyin .field_pinyin,
.show_pinyin2 .field_pinyin2,
.show_category_fr .field_category_fr,
.show_definition_fr .field_definition_fr,
.show_example .field_example,
.show_id .field_id,
.show_level .field_level,
.show_list .field_list,
.show_checkbox .field_checkbox {
display: initial;
}
#dict_table td{
width: 100vw;
}
#dict_table label{
display: block
}
body:has(.modal-toggle:checked), body:has(.drawer-toggle:checked) {
overflow-y: hidden;
}
.modal-box .btn-ghost:hover {
background-color: initial
}
`
let elm = document.createElement('style')
elm.innerHTML = css
elm.id = 'dict_table_style'
document.head.insertAdjacentElement('beforeend', elm)
}
}
async function loadDict(){
cnDict.settings ??= _.saveUserSettings('', 'localStorage') || {}
delete cnDict.settings.search
cnDict.data.hsk ??= await fetch('data/hskvocab/hskvocab.json').then(x=>x.json())
;['list-1', 'list-2', 'list-3', 'list-4'].forEach(key=>{
if(cnDict.settings[key]){
cnDict.settings[key].forEach(n=>{
cnDict.data.hsk.value[n].list = key
})
}
else cnDict.settings[key] = []
})
let pinyin2 = await fetch('data/hskvocab/hskextra.json').then(x=>x.json())
pinyin2.forEach((val, n)=>{
Object.keys(val).forEach(x=>{
cnDict.data.hsk.value[n][x] = val[x]
})
})
}
function handleModal(event){
// initialize
if(typeof event == 'undefined'){
let options, elms, name, option, type, html, userOptions
options = {
offset: [1, '20%', '40%', '60%', '80%'],
checkbox: [1, 'list-1', 'list-2', 'list-3', 'list-4'],
list: [1, 'list-1', 'list-2', 'list-3', 'list-4'],
level: [1, 'hsk-1', 'hsk-2', 'hsk-3', 'hsk-4', 'hsk-5', 'hsk-6', 'extra'],
field: Object.keys(cnDict.data.hsk.value[0]),
sort: [1, 'random', 'pinyin'],
export: [2, 'export_data'],
}
options.field.unshift(0)
options.field.push('list', 'pinyin2')
userOptions = cnDict.settings
html = ''
Object.keys(options).forEach(key=>{
html += `<br><button class="btn btn-ghost no-animation btn-xs sm:btn-sm my-2">${key}</button>`
})
html = html.replace('<br>', '')
document.querySelector('#dict_options_modal .modal-box').insertAdjacentHTML('beforeend', html)
elms = document.querySelectorAll('#dict_options_modal .btn-ghost')
elms.forEach(elm=>{
name = elm.innerText.toLowerCase()
option = options[name] || []
type = ['accent', 'info', 'warning'][option.shift()]
html = ''
option.forEach(item=>{
let itemName = type=='info'?name:name+'_'+item
let itemState = (userOptions[itemName] == 1 || userOptions[itemName] == item) ? '' : 'btn-outline ';
html += ` <button class="btn ${itemState}btn-${type} btn-xs sm:btn-sm my-2" name="${itemName}" value="${type=='info'?item:1}" onclick="handleModal(event)">${item}</button>`
})
elm.insertAdjacentHTML('afterend', html)
})
if(Object.keys(cnDict.settings).length < 5){
elms = document.querySelectorAll('.modal-box [name^=field_]')
elms.forEach(x=>{
cnDict.settings[x.name] = +x.value
x.classList.remove('btn-outline')
})
}
document.querySelector('[name=search]').closest('form').onsubmit = (event)=>{
cnDict.settings.search = event.target.querySelector('input').value
document.querySelector('.drawer-overlay').click();
handleDisplay('')
return false
}
}
// onclick button
else {
let elms, target, val
target = event.target
elms = document.querySelectorAll('.modal-box [name='+target.name+']')
val = target.classList.contains('btn-outline') ? target.value : 0
if(elms.length == 1 || val == 0){
target.classList.toggle('btn-outline')
}
else {
elms.forEach(elm=>elm.classList.add('btn-outline'))
target.classList.remove('btn-outline')
}
if(!target.className.includes('warning')) {
val = isNaN(+val) ? val : +val
cnDict.settings[target.name] = val
_.saveUserSettings(cnDict.settings, 'localStorage')
}
if(target.innerText.includes('export')){
if(val == 1) {
target.insertAdjacentHTML('afterend', `<div><textarea placeholder="json" class="textarea textarea-bordered textarea-sm w-full" ></textarea></div>
`)
elms = document.querySelector('.modal-box')
elms.scrollTo(0, elms.scrollHeight)
elms = elms.querySelector('textarea')
elms.value = JSON.stringify(cnDict.settings)
}
else {
elms = document.querySelector('.modal-box textarea')
let json = elms.value
try{
JSON.parse(json)
if(json != JSON.stringify(cnDict.settings)){
_.saveUserSettings(json, 'localStorage')
location.reload()
}
}
catch(e){
}
elms.remove()
}
}
else {
handleDisplay(target.name)
}
}
}
/*
id
simplified 1
traditional 2
pinyin 3
category_fr 4
definition_fr 5
example
level
*/
function handleDisplay(event){
let userOptions, data, filtered, html, tbody, row, elms, tmp, a, b, c
userOptions = cnDict.settings
data = cnDict.data.hsk.value
tbody = document.querySelector('#dict_table tbody')
// initialize
if(typeof event == 'undefined'){
Object.keys(userOptions).forEach(key=>{
if(key.startsWith('field') && userOptions[key] == 1){
tbody.classList.add(key.replace('field', 'show'))
}
})
if(userOptions.checkbox) {
tbody.classList.add('show_checkbox')
}
}
// hide show checkbox
else if(typeof event == 'string'){
if(event.startsWith('field')) {
tbody.classList.toggle(event.replace('field', 'show'))
return
}
else if(event.startsWith('checkbox')){
let fn
elms = tbody.querySelectorAll('label')
if(userOptions.checkbox) {
tbody.classList.add('show_checkbox')
fn = x=>x.removeAttribute('for')
}
else {
tbody.classList.remove('show_checkbox')
fn = x=>x.setAttribute('for', '')
}
elms.forEach(x=>{
fn(x)
x = x.querySelector('input')
x.checked = data[x.value].list == userOptions.checkbox
x.className = x.className.replace(/checkbox-\w{3,10}/, '') + ' ' + ['', 'checkbox-error', 'checkbox-warning', 'checkbox-success', 'checkbox-info'][userOptions.checkbox?userOptions.checkbox.substring(5):0]
})
return
}
else{
tbody.innerHTML = ''
}
}
// handle checkbox event
else if(typeof event == 'object'){
let prev, n, m, val
elms = event.target
prev = userOptions.checkbox
val = ''
m = 0
if(elms.checked) {
m = prev.at(-1)
userOptions[prev].push(+elms.value)
val = prev
prev = data[elms.value].list
}
if(prev){
row = userOptions[prev]
n = row.indexOf(elms.value)
row[n] = row.at(-1)
row.pop()
prev = -1
}
elms = elms.closest('label').querySelector('.field_list')
elms.innerText = val
elms.className = elms.className.replace(/ ?text-[^ ]+/, '') + ' ' + ['', 'text-error', 'text-warning', 'text-success', 'text-info'][m]
_.saveUserSettings(cnDict.settings, 'localStorage')
return
}
filtered = data
;['level', 'list'].forEach(key=>{
if(userOptions[key]) {
tmp = filtered
filtered = []
tmp.forEach(line=>{
if(
line[key] == userOptions[key] ||
(userOptions[key] == 'extra' && line[key].length == 6)
){
filtered.push(line)
}
})
}
})
if(filtered == data) filtered = [...data]
if(userOptions.search){
let key, search, tmp, a
key = /\w/.test(userOptions.search) ? (/\d/.test(userOptions.search) ? 'pinyin' : 'definition_fr') : 'simplified'
search = userOptions.search.trim().split(' ')
tmp = filtered
filtered = []
tmp.forEach(line=>{
for(a=0; a<search.length; a++){
if(line[key].includes(search[a])){
filtered.push(line)
break
}
}
})
}
if(userOptions.offset){
a = (+(userOptions.offset.replace('%',''))/100 * filtered.length) | 0
filtered = [...filtered.slice(a)]
}
if(userOptions.sort == 'random'){
for(a=filtered.length; a>1; a--){
b = (Math.random() * a) | 0
;([filtered[b], filtered[a-1]] = [filtered[a-1], filtered[b]])
}
}
else if(userOptions.sort == 'pinyin'){
filtered.sort((x, y) => {
return x.pinyin2 < y.pinyin2 ? -1 : x.pinyin2 > y.pinyin2 ? 1 : 0
})
}
/*
html = ''
filtered.slice(0, 10).forEach(line=>{
row = '<tr><td><label>'
row += `<span class="field_checkbox"><input name="checkbox" type="checkbox" ${line.list == userOptions.checkbox ? 'checked' : ''} class="checkbox checkbox-xs ${['', 'checkbox-error', 'checkbox-warning', 'checkbox-success', 'checkbox-info'][userOptions.checkbox?userOptions.checkbox.substring(5):0]}" onchange="handleDisplay(event)" value="${line.id}"> </span>`
row += `<span class="field_simplified">${line.simplified} </span>`
row += `<span class="field_traditional">【${line.traditional}】 </span>`
row += `<span class="field_pinyin">${line.pinyin}</span>`
row += '<br class="field_br1">'
row += `<span class="field_category_fr">${line.category_fr} </span>`
row += `<span class="field_definition_fr">${line.definition_fr}</span>`
row += '<br class="field_br2">'
row += `<span class="field_example">${line.example}</span>`
row += '<br class="field_br3">'
row += `<span class="field_id">#${line.id} </span>`
row += `<span class="field_level">${line.level} </span>`
row += `<span class="field_list">${line.list || ''}</span>`
row += '</label></td></tr>'
html += row
})
tbody.insertAdjacentHTML('beforeend', html)
*/
handleDisplay2(filtered)
}
function handleDisplay2(event){
function renderHTML(line){
let listOpt = ['', 'checkbox-error', 'checkbox-warning', 'checkbox-success', 'checkbox-info']
let row = ''
row = `<tr><td><label${cnDict.settings.checkbox ? '' : ' for'}><div>`
row += `<span class="field_checkbox"><input name="checkbox" type="checkbox" ${line.list == cnDict.settings.checkbox ? 'checked' : ''} class="checkbox checkbox-xs ${listOpt[cnDict.settings.checkbox?cnDict.settings.checkbox.at(-1):0]}" onchange="handleDisplay(event)" value="${line.id}"> </span>`
row += `<span class="field_simplified">${line.simplified} </span>`
row += `<span class="field_traditional">【${line.traditional}】 </span>`
row += `<span class="field_pinyin">${line.pinyin} </span>`
row += `<span class="field_pinyin2">${line.pinyin2}</span>`
row += '</div><div>'
row += `<span class="field_category_fr">${line.category_fr} </span>`
row += `<span class="field_definition_fr">${line.definition_fr}</span>`
row += '</div><div>'
row += `<span class="field_example">${line.example}</span>`
row += '</div><div>'
row += `<span class="field_id">#${line.id} </span>`
row += `<span class="field_level">${line.level} </span>`
row += `<span class="field_list ${listOpt[line.list?.at(-1)||0].replace('checkbox', 'text')}">${line.list || ''}</span>`
row += '</label></td></tr>'
return row
}
document.querySelector('#dict_table tbody').innerHTML = ''
runVirtual2(event || cnDict.data.hsk.value.slice(0, 200), document.querySelector('#dict_table tbody'), renderHTML)
}
function runVirtual2(items, container, fn) {
if(!document.querySelector('#virtualizer_style')){
document.head.insertAdjacentHTML('beforeend', `
<style id="virtualizer_style">
html, body{
height: 100vh;
margin: 0px;
overflow-y: auto;
}
</style>
`)
// const items = new Array(500).fill(true).map(() => 25);
const m = 48 + 8*2 + 40
const virtualizer = new VirtualCore.Virtualizer({
count: items.length,
getScrollElement: () => document.body,
estimateSize: () => 20,
scrollMargin: m,
overscan: 2,
observeElementRect: VirtualCore.observeElementRect,
observeElementOffset: VirtualCore.observeElementOffset,
scrollToFn: VirtualCore.elementScroll,
onChange: (instance) => {
let indexes = []
let h, element, element2, elements = instance.getVirtualItems()
if(!elements.length) return
if(!instance.options._container){
instance.options._items = items
instance.options._container = container
instance.options._fn = fn
items = container = fn = undefined
}
// const container = document.querySelector('#list');
h = Math.min(instance.getTotalSize(), elements.at(-1).start-m+200)
if (h>instance.options._container.offsetHeight) {
instance.options._container.style.height = `${h}px`;
}
// console.log(elements.length)
for(element of elements){
// console.log(elements.length, element.index)
indexes.push(element.index)
element2 = instance.measureElementCache.get(element.index)
if(element2){
if(element2.style.transform != `translateY(${element.start-m}px)`){
element2.style.transform = `translateY(${element.start-m}px)`
}
continue
}
const row = document.createElement('tr');
row.style.position = 'absolute';
// li.style.height = `${element.size}px`;
row.style.transform = `translateY(${element.start-m}px)`;
// row.innerHTML = `Item ${element.index}` + (element.index % 2 ? '<br>-----' : '');
row.innerHTML = instance.options._fn(instance.options._items[element.index])
row.style.top = 0;
row.style.left = 0;
row.dataset.index = element.index
instance.options._container.append(row);
instance.measureElement(row)
return
}
for(element of instance.measureElementCache){
if(indexes.includes(+element[0])) continue;
element[1].remove();
instance.measureElementCache.delete(element[0])
}
},
});
virtualizer._willUpdate();
window.vv = virtualizer
return
}
else {
if(vv.options._items?.length && items.length) vv.scrollToIndex(0)
vv.measurementsCache = []
vv.measureElementCache = new Map()
vv.itemSizeCache = new Map()
vv.options.count = 0
vv.options._items = []
vv.options._container.style.height = '0px'
// document.querySelector('tbody').innerHTML = ''
for(let elm = document.querySelector('tbody'); elm.firstChild; elm.removeChild(elm.firstChild));
vv.options._items = items
vv.options.count = items.length
vv.notify(true)
}
}