File size: 10,193 Bytes
986a1e3
47f6034
 
 
986a1e3
f2b38ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9da2ec3
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
/**
 * HÁN VIỆT TỪ ĐIỂN - 2025
 * Phiên bản viết bởi Long Ngo, dự án này được hỗ trợ bởi CVNSS4.0 xem tại https://chuvnsongsong.com/
 * Xin chân thành cảm ơn 2 Nhà nghiên cứu: Anh Kiều Trường Lâm và Thầy Trần Tư Bình đã ủng hộ cho Dự án.
 */

$(document).ready(function() {
    
    // --- BIẾN TOÀN CỤC ---
    let dictData = []; // Sẽ lấy từ dictionaryData.js
    let radData = [];  // Sẽ lấy từ bothudata.js
    
    // Canvas vars
    let canvas = document.getElementById('handCanvas');
    let ctx = canvas.getContext('2d');
    let isDrawing = false;
    let strokeCount = 0;

    // --- KHỞI TẠO DỮ LIỆU ---
    initData();
    initEvents();

    function initData() {
        // Kiểm tra xem file dictionaryData.js đã load chưa
        if (typeof localDictionary !== 'undefined') {
            dictData = localDictionary;
        } else if (typeof dictionaryData !== 'undefined') {
            dictData = dictionaryData; // Fallback
        } else {
            $('#searchCount').text("Lỗi: Không tìm thấy dữ liệu từ điển!");
        }

        // Kiểm tra file bothudata.js
        if (typeof universalRadical !== 'undefined') {
            radData = universalRadical;
            initRadicalDropdown();
            renderRadicals(0); // Render all initially
        }

        // Render trang đầu
        renderList(dictData.slice(0, 50)); // Load 50 từ đầu tiên
        $('#searchCount').text(`Tổng: ${dictData.length} mục từ`);
        
        // Init Canvas Style
        ctx.lineWidth = 6;
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';
        ctx.strokeStyle = '#2C2C2C';
    }

    // --- XỬ LÝ SỰ KIỆN (EVENTS) ---
    function initEvents() {
        // 1. Chuyển Tab
        $('.nav-btn').click(function() {
            const tabId = $(this).data('tab');
            
            // UI Update
            $('.nav-btn').removeClass('active');
            $(this).addClass('active');
            
            $('.view-section').removeClass('active');
            $(`#view-${tabId}`).addClass('active');

            // Mobile sidebar logic
            if ($(window).width() <= 768) {
                openSidebar();
            }
        });

        // 2. Tìm kiếm (Debounce nhẹ)
        let searchTimeout;
        $('#searchInput').on('keyup', function() {
            clearTimeout(searchTimeout);
            const keyword = $(this).val().toLowerCase();
            searchTimeout = setTimeout(() => {
                handleSearch(keyword);
            }, 300);
        });

        // 3. Mobile Toggle
        $('#btnToggleSidebar').click(toggleSidebar);
        $('#overlay').click(closeSidebar);

        // 4. Canvas Events
        $('#btnRecognize').click(recognizeHandwriting);
        $('#btnClearHand').click(clearCanvas);
        
        // Mouse/Touch drawing
        $(canvas).on('mousedown touchstart', startDraw);
        $(canvas).on('mousemove touchmove', draw);
        $(canvas).on('mouseup mouseout touchend', stopDraw);
        
        // Prevent scrolling when drawing on mobile
        $(canvas).on('touchstart touchmove', function(e) { e.preventDefault(); });
    }

    // --- LOGIC TÌM KIẾM & HIỂN THỊ LIST ---
    function handleSearch(keyword) {
        if (!keyword) {
            renderList(dictData.slice(0, 50));
            $('#searchCount').text(`Tổng: ${dictData.length} mục từ`);
            return;
        }

        const results = dictData.filter(item => {
            return item.hanviet.toLowerCase().includes(keyword);
        });

        renderList(results.slice(0, 100)); // Limit render
        $('#searchCount').text(`Tìm thấy ${results.length} kết quả`);
    }

    function renderList(items) {
        const list = $('#textResultList');
        list.empty();

        items.forEach(item => {
            // Tách chữ Hán và phiên âm (Giả định format: "Chữ PhienAm Nghia...")
            // Format thường gặp trong file data của bạn: "HánViệt..."
            let displayHan = "";
            let displayViet = "";
            
            if (item.hanviet) {
                const parts = item.hanviet.split(' ');
                displayHan = parts[0];
                displayViet = parts.slice(1).join(' ');
            }

            const li = $(`
                <li class="list-item" data-id="${item.id}">
                    <span class="item-han">${displayHan}</span>
                    <span class="item-viet">${displayViet}</span>
                </li>
            `);
            
            li.click(() => showDetail(item));
            list.append(li);
        });
    }

    // --- LOGIC HIỂN THỊ CHI TIẾT ---
    function showDetail(item) {
        // Tự động đóng sidebar trên mobile
        if ($(window).width() <= 768) {
            closeSidebar();
        }

        const parts = item.hanviet.split(' ');
        const char = parts[0];
        const phonetics = parts.slice(1).join(' ');

        // Format lại nghĩa (thay thế ký tự đặc biệt)
        let formattedMean = item.nghia || "";
        formattedMean = formattedMean.replace(/◇/g, '<br><span class="meaning-label">◇</span>');
        formattedMean = formattedMean.replace(/♦/g, '<br><span class="meaning-label">♦</span>');
        formattedMean = formattedMean.replace(/§/g, '<span class="meaning-label">§</span>');

        const html = `
            <div class="detail-header">
                <div class="big-char">${char}</div>
                <div class="detail-meta">
                    <div class="hanviet-main">${phonetics}</div>
                    <div class="pinyin">Unicode: U+${char.charCodeAt(0).toString(16).toUpperCase()}</div>
                </div>
            </div>
            <div class="meaning-group">
                ${formattedMean}
            </div>
        `;

        $('#detailCard').html(html);
        
        // Highlight active item
        $('.list-item').removeClass('selected');
        $(`.list-item[data-id="${item.id}"]`).addClass('selected');
    }

    // --- LOGIC BỘ THỦ ---
    function initRadicalDropdown() {
        // Tạo set các số nét để render dropdown
        // Format radData: "số_nét|ký_tự|..."
        // Bỏ qua phần tử 0 rỗng
        for(let i=1; i<=17; i++) { // Max nét bộ thủ thường là 17
            $('#radicalStrokes').append(`<option value="${i}">${i} nét</option>`);
        }
        
        $('#radicalStrokes').change(function() {
            renderRadicals($(this).val());
        });
    }

    function renderRadicals(strokeCount) {
        const grid = $('#radicalList');
        grid.empty();
        
        // Bỏ qua index 0
        for (let i = 1; i < radData.length; i++) {
            const line = radData[i];
            const parts = line.split('|');
            if (parts.length < 4) continue;

            const rStroke = parts[0];
            const rChar = parts[1];
            const rPinyin = parts[2];
            const rViet = parts[3];

            if (strokeCount == 0 || rStroke == strokeCount) {
                const box = $(`
                    <div class="radical-box" title="${rViet} (${rPinyin})">
                        <span class="r-char">${rChar}</span>
                        <span class="r-stroke">${rStroke}n</span>
                    </div>
                `);
                
                box.click(() => {
                    // Chuyển sang tab search và tìm theo bộ thủ này
                    $('.nav-btn[data-tab="text"]').click();
                    $('#searchInput').val(rChar);
                    handleSearch(rChar);
                });
                
                grid.append(box);
            }
        }
    }

    // --- LOGIC VIẾT TAY (CANVAS) ---
    function startDraw(e) {
        isDrawing = true;
        strokeCount++; // Đếm nét sơ bộ
        draw(e);
    }
    
    function stopDraw() {
        isDrawing = false;
        ctx.beginPath(); // Reset path để nét sau không dính nét trước
    }

    function draw(e) {
        if (!isDrawing) return;
        
        const rect = canvas.getBoundingClientRect();
        let clientX, clientY;
        
        if (e.type.includes('touch')) {
            clientX = e.touches[0].clientX;
            clientY = e.touches[0].clientY;
        } else {
            clientX = e.clientX;
            clientY = e.clientY;
        }

        const x = clientX - rect.left;
        const y = clientY - rect.top;

        ctx.lineTo(x, y);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(x, y);
    }

    function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        strokeCount = 0;
        $('#handResults').empty();
    }

    function recognizeHandwriting() {
        // Giả lập nhận dạng để UI hoạt động
        // (Logic thực tế sẽ cần port từ file handict.js cũ vốn rất phức tạp)
        const resDiv = $('#handResults');
        resDiv.html('<div style="width:100%; text-align:center; color:#888;">Đang phân tích...</div>');
        
        setTimeout(() => {
            resDiv.empty();
            // Demo vài chữ
            const demo = ["一", "人", "大", "木", "本"];
            demo.forEach(c => {
                const item = $(`<div class="hand-res-item">${c}</div>`);
                item.click(() => {
                    $('.nav-btn[data-tab="text"]').click();
                    $('#searchInput').val(c);
                    handleSearch(c);
                });
                resDiv.append(item);
            });
        }, 500);
    }

    // --- UI HELPERS ---
    function toggleSidebar() {
        $('#sidebar').toggleClass('open');
        $('#overlay').toggleClass('active');
    }
    
    function openSidebar() {
        $('#sidebar').addClass('open');
        $('#overlay').addClass('active');
    }

    function closeSidebar() {
        $('#sidebar').removeClass('open');
        $('#overlay').removeClass('active');
    }

});