Upload vietuni-cvnss.js
Browse files- vietuni-cvnss.js +532 -0
vietuni-cvnss.js
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* VIETUNI-CVNSS PROFESSIONAL INTEGRATION
|
| 3 |
+
* Fixed: Spacebar Trigger, Modern Browser Support
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
/* ========================================================================== */
|
| 7 |
+
/* PHẦN 1: CORE CVNSS 4.0 CONVERTER (FULL DATA) */
|
| 8 |
+
/* ========================================================================== */
|
| 9 |
+
const CVNSSConverter = (function () {
|
| 10 |
+
const specialChars = [
|
| 11 |
+
"`", "“", "”", "<", ">", "@", "-", ";", "=", "…", ",", ".", "?", "!",
|
| 12 |
+
'"', "'", "(", ")", "[", "]", "{", "}", "%", "#", "$", "&", "_", "\\", "/",
|
| 13 |
+
"*", ":", "+", "~", "^", "|", "\r\n", "\r", "\n"
|
| 14 |
+
];
|
| 15 |
+
|
| 16 |
+
const consonants = {
|
| 17 |
+
cqn: ["ngh", "ng", "ch", "gh", "kh", "nh", "ph", "th", "tr", "gi", "qu", "b", "k", "d", "đ", "g", "h", "c", "l", "m", "n", "r", "s", "t", "v", "x"],
|
| 18 |
+
cvn: ["w", "w", "ch", "g", "k", "nh", "f", "th", "tr", "j", "q", "b", "c", "z", "d", "g", "h", "c", "l", "m", "n", "r", "s", "t", "v", "x"]
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
// FULL DATA VOWELS FROM YOUR FILE
|
| 22 |
+
const vowels = {
|
| 23 |
+
cqn: ["a","à","ả","ã","á","ạ","oa","òa","ỏa","õa","óa","ọa","oà","oả","oã","oá","oạ","oác","oạc","oách","oạch","oai","oài","oải","oãi","oái","oại","oao","oào","oảo","oão","oáo","oạo","oáp","oạp","oát","oạt","oắt","oặt","oắc","oặc","oăn","oằn","oẳn","oẵn","oắn","oặn","oăm","oằm","oẳm","oẵm","oắm","oặm","oăng","oằng","oẳng","oẵng","oắng","oặng","oay","oày","oảy","oãy","oáy","oạy","ác","ạc","ách","ạch","ai","ài","ải","ãi","ái","ại","am","àm","ảm","ãm","ám","ạm","an","àn","ản","ãn","án","ạn","oan","oàn","oản","oãn","oán","oạn","oanh","oành","oảnh","oãnh","oánh","oạnh","ang","àng","ảng","ãng","áng","ạng","oang","oàng","oảng","oãng","oáng","oạng","anh","ành","ảnh","ãnh","ánh","ạnh","ao","ào","ảo","ão","áo","ạo","áp","ạp","át","ạt","au","àu","ảu","áu","ạu","ay","ày","ảy","ãy","áy","ạy","ắc","ặc","ăm","ằm","ẳm","ẵm","ắm","ặm","ăn","ằn","ẳn","ẵn","ắn","ặn","ăng","ằng","ẳng","ẵng","ắng","ặng","ắp","ặp","ắt","ặt","ấc","ậc","âm","ầm","ẩm","ẫm","ấm","ậm","ân","ần","ẩn","ẫn","ấn","ận","âng","ầng","ẩng","ẫng","ấng","ậng","uân","uần","uẩn","uẫn","uấn","uận","uâng","uầng","uẩng","uẫng","uấng","uậng","ấp","ập","ất","ật","uất","uật","âu","ầu","ẩu","ẫu","ấu","ậu","ây","ầy","ẩy","ẫy","ấy","ậy","uây","uầy","uẩy","uẫy","uấy","uậy","e","è","ẻ","ẽ","é","ẹ","oe","òe","ỏe","õe","óe","ọe","éc","ẹc","em","èm","ẻm","ẽm","ém","ẹm","en","èn","ẻn","ẽn","én","ẹn","oen","oèn","oẻn","oẽn","oén","oẹn","eng","èng","ẻng","ẽng","éng","ẹng","eo","èo","ẻo","ẽo","éo","ẹo","oeo","oèo","oẻo","oẽo","oéo","oẹo","ép","ẹp","ét","ẹt","oét","oẹt","ê","ề","ể","ễ","ế","ệ","uê","uề","uể","uễ","uế","uệ","ếch","ệch","uếch","uệch","êm","ềm","ểm","ễm","ếm","ệm","ên","ền","ển","ễn","ến","ện","ênh","ềnh","ểnh","ễnh","ếnh","ệnh","uênh","uềnh","uểnh","uễnh","uếnh","uệnh","ếp","ệp","ết","ệt","êu","ều","ểu","ễu","ếu","ệu","i","ì","ỉ","ĩ","í","ị","uy","ùy","ủy","ũy","úy","ụy","uỳ","uỷ","uỹ","uý","uỵ","ia","ìa","ỉa","ĩa","ía","ịa","uya","íc","ích","ịch","uých","uỵch","iếc","iệc","iêm","iềm","iểm","iễm","iếm","iệm","iên","iền","iển","iễn","iến","iện","uyên","uyền","uyển","uyễn","uyến","uyện","iêng","iềng","iểng","iễng","iếng","iệng","iếp","iệp","iết","iệt","uyết","uyệt","iêu","iều","iểu","iễu","iếu","iệu","yêt","yệt","yên","yền","yển","yễn","yến","yện","yêm","yềm","yểm","yễm","yếm","yệm","yêng","yềng","yểng","yễng","yếng","yệnh","yêu","yều","yểu","yễu","yếu","yệu","im","ìm","ỉm","ĩm","ím","ịm","in","ìn","ỉn","ĩn","ín","ịn","inh","ình","ỉnh","ĩnh","ính","ịnh","uynh","uỳnh","uỷnh","uỹnh","uýnh","uỵnh","íp","ịp","uýp","uỵp","ít","ịt","uýt","uỵt","iu","ìu","ỉu","ĩu","íu","ịu","uyu","uỳu","uỷu","uỹu","uýu","uỵu","uỳn","uỷn","uỹn","uýn","uỵn","o","ò","ỏ","õ","ó","ọ","óc","ọc","oi","òi","ỏi","õi","ói","ọi","om","òm","ỏm","õm","óm","ọm","on","òn","ỏn","õn","ón","ọn","ong","òng","ỏng","õng","óng","ọng","oóc","oong","oòng","oỏng","oõng","oóng","oòng","oọng","óp","ọp","ót","ọt","ô","ồ","ổ","ỗ","ố","ộ","ốc","ộc","ôi","ồi","ổi","ỗi","ối","ội","ôm","ồm","ổm","ỗm","ốm","ộm","ôn","ồn","ổn","ỗn","ốn","ộn","ông","ồng","ổng","ỗng","ống","ộng","ốp","ộp","ốt","ột","ơ","ờ","ở","ỡ","ớ","ợ","ơi","ời","ởi","ỡi","ới","ợi","ơm","ờm","ởm","ỡm","ớm","ợm","ơn","ờn","ởn","ỡn","ớn","ợn","ơng","ờng","ởng","ỡng","ớng","ợng","ớp","ợp","ớt","ợt","u","ù","ủ","ũ","ú","ụ","ua","ùa","ủa","ũa","úa","ụa","úc","ục","ui","ùi","ủi","ũi","úi","ụi","um","ùm","ủm","ũm","úm","ụm","un","ùn","ủn","ũn","ún","ụn","ung","ùng","ủng","ũng","úng","ụng","uơ","uờ","uở","uỡ","uớ","uợ","uơn","uờn","uởn","uỡn","uớn","uợn","uớt","uợt","uốc","uộc","uôi","uồi","uổi","uỗi","uối","uội","uôm","uồm","uổm","uỗm","uốm","uộm","uôn","uồn","uổn","uỗn","uốn","uộn","uông","uồng","uổng","uỗng","uống","uộng","uốt","uột","uốp","uộp","úp","ụp","út","ụt","ư","ừ","ử","ữ","ứ","ự","ưa","ừa","ửa","ữa","ứa","ựa","ức","ực","ưi","ừi","ửi","ữi","ứi","ựi","ưm","ừm","ửm","ữm","ứm","ựm","ưn","ừn","ửn","ữn","ứn","ựn","ưng","ừng","ửng","ững","ứng","ựng","ước","ược","ươi","ười","ưởi","ưỡi","ưới","ượi","ươm","ườm","ưởm","ưỡm","ướm","ượm","ươn","ườn","ưởn","ưỡn","ướn","ượn","ương","ường","ưởng","ưỡng","ướng","ượng","ướp","ượp","ướt","ượt","ươu","ườu","ưởu","ưỡu","ướu","ượu","ứt","ựt","ưu","ừu","ửu","ữu","ứu","ựu","y","ỳ","ỷ","ỹ","ý","ỵ","ỳa","ỷa","ỹa","ýa","ỵa"],
|
| 24 |
+
cvn: ["a","al","az","as","aj","ar","oa","oal","oaz","oas","oaj","oar","oal","oaz","oas","oaj","oar","osj","osr","oakj","oakr","ojp","ojl","ojz","ojs","ojj","ojr","owp","owl","owz","ows","owj","owr","ofj","ofr","odj","odr","adx","adh","asx","ash","alo","alk","alv","alw","alx","alh","avo","avk","avv","avw","avx","avh","azo","azk","azv","azw","azx","azh","ajp","ajl","ajz","ajs","ajj","ajr","ac","acr","akj","akr","ai","ail","aiz","ais","aij","air","am","aml","amz","ams","amj","amr","an","anl","anz","ans","anj","anr","olp","oll","olz","ols","olj","olr","oahp","oahl","oahz","oahs","oahj","oahr","agp","agl","agz","ags","agj","agr","ozp","ozl","ozz","ozs","ozj","ozr","ahp","ahl","ahz","ahs","ahj","ahr","ao","aol","aoz","aos","aoj","aor","ap","apr","at","atr","au","aul","auz","auj","aur","ay","ayl","ayz","ays","ayj","ayr","acx","ach","amo","amk","amv","amw","amx","amh","ano","ank","anv","anw","anx","anh","ago","agk","agv","agw","agx","agh","apx","aph","atx","ath","acb","acf","amy","amd","amq","amg","amb","amf","any","and","anq","ang","anb","anf","agy","agd","agq","agg","agb","agf","aly","ald","alq","alg","alb","alf","azy","azd","azq","azg","azb","azf","apb","apf","atb","atf","adb","adf","auy","aud","auq","aug","aub","auf","ayy","ayd","ayq","ayg","ayb","ayf","ajy","ajd","ajq","ajg","ajb","ajf","e","el","ez","es","ej","er","oe","oel","oez","oes","oej","oer","ec","ecr","em","eml","emz","ems","emj","emr","en","enl","enz","ens","enj","enr","elp","ell","elz","els","elj","elr","egp","egl","egz","egs","egj","egr","eo","eol","eoz","eos","eoj","eor","ewp","ewl","ewz","ews","ewj","ewr","ep","epr","et","etr","edj","edr","ey","ed","eq","eg","eb","ef","uey","ued","ueq","ueg","ueb","uef","ekb","ekf","uekb","uekf","emy","emd","emq","emg","emb","emf","eny","end","enq","eng","enb","enf","ehy","ehd","ehq","ehg","ehb","ehf","uehy","uehd","uehq","uehg","uehb","uehf","epb","epf","etb","etf","euy","eud","euq","eug","eub","euf","i","il","iz","is","ij","ir","y","yl","yz","ys","yj","yr","yl","yz","ys","yj","yr","ia","ial","iaz","ias","iaj","iar","ya","ic","ikj","ikr","ykj","ykr","isb","isf","ivy","ivd","ivq","ivg","ivb","ivf","ily","ild","ilq","ilg","ilb","ilf","yly","yld","ylq","ylg","ylb","ylf","izy","izd","izq","izg","izb","izf","ifb","iff","idb","idf","ydb","ydf","iwy","iwd","iwq","iwg","iwb","iwf","idb","idf","ily","ild","ilq","ilg","ilb","ilf","ivy","ivd","ivq","ivg","ivb","ivf","izy","izd","izq","izg","izb","izf","iwy","iwd","iwq","iwg","iwb","iwf","im","iml","imz","ims","imj","imr","in","inl","inz","ins","inj","inr","ihp","ihl","ihz","ihs","ihj","ihr","yhp","yhl","yhz","yhs","yhj","yhr","ip","ipr","yp","ypr","it","itr","yt","ytr","iu","iul","iuz","ius","iuj","iur","yu","yul","yuz","yus","yuj","yur","ynl","ynz","yns","ynj","ynr","o","ol","oz","os","oj","or","oc","ocr","oi","oil","oiz","ois","oij","oir","om","oml","omz","oms","omj","omr","on","onl","onz","ons","onj","onr","ogp","ogl","ogz","ogs","ogj","ogr","ooc","oog","oogl","oogz","oogs","oogj","oogl","oogr","op","opr","ot","otr","oy","od","oq","og","ob","of","ocb","ocf","oiy","oid","oiq","oig","oib","oif","omy","omd","omq","omg","omb","omf","ony","ond","onq","ong","onb","onf","ogy","ogd","ogq","ogg","ogb","ogf","opb","opf","otb","otf","oo","ok","ov","ow","ox","oh","oio","oik","oiv","oiw","oix","oih","omo","omk","omv","omw","omx","omh","ono","onk","onv","onw","onx","onh","ogo","ogk","ogv","ogw","ogx","ogh","opx","oph","otx","oth","u","ul","uz","us","uj","ur","ua","ual","uaz","uas","uaj","uar","uc","ucr","ui","uil","uiz","uis","uij","uir","um","uml","umz","ums","umj","umr","un","unl","unz","uns","unj","unr","ugp","ugl","ugz","ugs","ugj","ugr","uoo","uok","uov","uow","uox","uoh","olo","olk","olv","olw","olx","olh","odx","odh","usb","usf","ujy","ujd","ujq","ujg","ujb","ujf","uvy","uvd","uvq","uvg","uvb","uvf","uly","uld","ulq","ulg","ulb","ulf","uzy","uzd","uzq","uzg","uzb","uzf","udb","udf","ufb","uff","up","upr","ut","utr","uo","uk","uv","uw","ux","uh","uao","uak","uav","uaw","uax","uah","ucx","uch","uio","uik","uiv","uiw","uix","uih","umo","umk","umv","umw","umx","umh","uno","unk","unv","unw","unx","unh","ugo","ugk","ugv","ugw","ugx","ugh","usx","ush","ujo","ujk","ujv","ujw","ujx","ujh","uvo","uvk","uvv","uvw","uvx","uvh","ulo","ulk","ulv","ulw","ulx","ulh","uzo","uzk","uzv","uzw","uzx","uzh","ufx","ufh","udx","udh","uwo","uwk","uwv","uww","uwx","uwh","utx","uth","uuo","uuk","uuv","uuw","uux","uuh","i","il","iz","is","ij","ir","ial","iaz","ias","iaj","iar"],
|
| 25 |
+
cvss: ["a","al","az","as","aj","ar","oa","oal","oaz","oas","oaj","oar","oal","oaz","oas","oaj","oar","osj","osr","oakj","oakr","ojp","ojl","ojz","ojs","ojj","ojr","owp","owl","owz","ows","owj","owr","ofj","ofr","odj","odr","adx","adh","asx","ash","alo","alk","alv","alw","alx","alh","avo","avk","avv","avw","avx","avh","azo","azk","azv","azw","azx","azh","ajp","ajl","ajz","ajs","ajj","ajr","ac","acr","akj","akr","ai","ail","aiz","ais","aij","air","am","aml","amz","ams","amj","amr","an","anl","anz","ans","anj","anr","olp","oll","olz","ols","olj","olr","oahp","oahl","oahz","oahs","oahj","oahr","agp","agl","agz","ags","agj","agr","ozp","ozl","ozz","ozs","ozj","ozr","ahp","ahl","ahz","ahs","ahj","ahr","ao","aol","aoz","aos","aoj","aor","ap","apr","at","atr","au","aul","auz","auj","aur","ay","ayl","ayz","ays","ayj","ayr","acx","ach","amo","amk","amv","amw","amx","amh","ano","ank","anv","anw","anx","anh","ago","agk","agv","agw","agx","agh","apx","aph","atx","ath","acb","acf","amy","amd","amq","amg","amb","amf","any","and","anq","ang","anb","anf","agy","agd","agq","agg","agb","agf","aly","ald","alq","alg","alb","alf","azy","azd","azq","azg","azb","azf","apb","apf","atb","atf","adb","adf","auy","aud","auq","aug","aub","auf","ayy","ayd","ayq","ayg","ayb","ayf","ajy","ajd","ajq","ajg","ajb","ajf","e","el","ez","es","ej","er","oe","oel","oez","oes","oej","oer","ec","ecr","em","eml","emz","ems","emj","emr","en","enl","enz","ens","enj","enr","elp","ell","elz","els","elj","elr","egp","egl","egz","egs","egj","egr","eo","eol","eoz","eos","eoj","eor","ewp","ewl","ewz","ews","ewj","ewr","ep","epr","et","etr","edj","edr","ey","ed","eq","eg","eb","ef","uey","ued","ueq","ueg","ueb","uef","ekb","ekf","uekb","uekf","emy","emd","emq","emg","emb","emf","eny","end","enq","eng","enb","enf","ehy","ehd","ehq","ehg","ehb","ehf","uehy","uehd","uehq","uehg","uehb","uehf","epb","epf","etb","etf","euy","eud","euq","eug","eub","euf","i","il","iz","is","ij","ir","y","yl","yz","ys","yj","yr","yl","yz","ys","yj","yr","ia","ial","iaz","ias","iaj","iar","ya","ic","ikj","ikr","ykj","ykr","isb","isf","ivy","ivd","ivq","ivg","ivb","ivf","ily","ild","ilq","ilg","ilb","ilf","yly","yld","ylq","ylg","ylb","ylf","izy","izd","izq","izg","izb","izf","ifb","iff","idb","idf","ydb","ydf","iwy","iwd","iwq","iwg","iwb","iwf","idb","idf","ily","ild","ilq","ilg","ilb","ilf","ivy","ivd","ivq","ivg","ivb","ivf","izy","izd","izq","izg","izb","izf","iwy","iwd","iwq","iwg","iwb","iwf","im","iml","imz","ims","imj","imr","in","inl","inz","ins","inj","inr","ihp","ihl","ihz","ihs","ihj","ihr","yhp","yhl","yhz","yhs","yhj","yhr","ip","ipr","yp","ypr","it","itr","yt","ytr","iu","iul","iuz","ius","iuj","iur","yu","yul","yuz","yus","yuj","yur","ynl","ynz","yns","ynj","ynr","o","ol","oz","os","oj","or","oc","ocr","oi","oil","oiz","ois","oij","oir","om","oml","omz","oms","omj","omr","on","onl","onz","ons","onj","onr","ogp","ogl","ogz","ogs","ogj","ogr","ooc","oog","oogl","oogz","oogs","oogj","oogl","oogr","op","opr","ot","otr","oy","od","oq","og","ob","of","ocb","ocf","oiy","oid","oiq","oig","oib","oif","omy","omd","omq","omg","omb","omf","ony","ond","onq","ong","onb","onf","ogy","ogd","ogq","ogg","ogb","ogf","opb","opf","otb","otf","oo","ok","ov","ow","ox","oh","oio","oik","oiv","oiw","oix","oih","omo","omk","omv","omw","omx","omh","ono","onk","onv","onw","onx","onh","ogo","ogk","ogv","ogw","ogx","ogh","opx","oph","otx","oth","u","ul","uz","us","uj","ur","ua","ual","uaz","uas","uaj","uar","uc","ucr","ui","uil","uiz","uis","uij","uir","um","uml","umz","ums","umj","umr","un","unl","unz","uns","unj","unr","ugp","ugl","ugz","ugs","ugj","ugr","uoo","uok","uov","uow","uox","uoh","olo","olk","olv","olw","olx","olh","odx","odh","usb","usf","ujy","ujd","ujq","ujg","ujb","ujf","uvy","uvd","uvq","uvg","uvb","uvf","uly","uld","ulq","ulg","ulb","ulf","uzy","uzd","uzq","uzg","uzb","uzf","udb","udf","ufb","uff","up","upr","ut","utr","uo","uk","uv","uw","ux","uh","uao","uak","uav","uaw","uax","uah","ucx","uch","uio","uik","uiv","uiw","uix","uih","umo","umk","umv","umw","umx","umh","uno","unk","unv","unw","unx","unh","ugo","ugk","ugv","ugw","ugx","ugh","usx","ush","ujo","ujk","ujv","ujw","ujx","ujh","uvo","uvk","uvv","uvw","uvx","uvh","ulo","ulk","ulv","ulw","ulx","ulh","uzo","uzk","uzv","uzw","uzx","uzh","ufx","ufh","udx","udh","uwo","uwk","uwv","uww","uwx","uwh","utx","uth","uuo","uuk","uuv","uuw","uux","uuh","i","il","iz","is","ij","ir","ial","iaz","ias","iaj","iar"]
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
const baseVowels = [
|
| 29 |
+
"aàảãáạ", "ăằẳẵắặ", "âầẩẫấậ", "eèẻẽéẹ", "êềểễếệ", "iìỉĩíị",
|
| 30 |
+
"oòỏõóọ", "ôồổỗốộ", "ơờởỡớợ", "uùủũúụ", "ưừửữứự", "yỳỷỹýỵ"
|
| 31 |
+
];
|
| 32 |
+
|
| 33 |
+
const specialReplacements = { y: "yỳỷỹýỵ", i: "iìỉĩíị" };
|
| 34 |
+
const consonantAdjustments = { phu_am: ["ngh", "gh", "k"], phu_am_chuyen_doi: ["ng", "g", "c"], nguyen_am: "ieê" };
|
| 35 |
+
|
| 36 |
+
function isUpperCase(str) {
|
| 37 |
+
return /^[A-ZÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬĐÈÉẺẼẸÊỀẾỂỄỆÌÍỈĨỊÒÓỎÕỌÔỒỐỔỖỘƠỜỚỞỠỢÙÚỦŨỤƯỪỨỬỮỰỲÝỶỸỴ]+$/.test(str);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
function getBaseVowel(char) {
|
| 41 |
+
for (const vowelGroup of baseVowels) {
|
| 42 |
+
if (vowelGroup.includes(char)) return vowelGroup[0];
|
| 43 |
+
}
|
| 44 |
+
return char;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
function adjustConsonantVowel(cqnPad, cqnVan) {
|
| 48 |
+
const firstChar = cqnVan[0] || "";
|
| 49 |
+
if (cqnPad === "qu" && getBaseVowel(firstChar) === "u") { cqnPad = "q"; }
|
| 50 |
+
if (!cqnPad && getBaseVowel(firstChar) === "i") {
|
| 51 |
+
cqnVan = cqnVan.replace(firstChar, specialReplacements.y[specialReplacements.i.indexOf(firstChar)]);
|
| 52 |
+
}
|
| 53 |
+
if (cqnPad === "gi" && getBaseVowel(firstChar) === "i") { cqnPad = "g"; }
|
| 54 |
+
if (consonantAdjustments.phu_am.includes(cqnPad) && !consonantAdjustments.nguyen_am.includes(getBaseVowel(firstChar))) {
|
| 55 |
+
cqnPad = consonantAdjustments.phu_am_chuyen_doi[consonantAdjustments.phu_am.indexOf(cqnPad)];
|
| 56 |
+
}
|
| 57 |
+
return { cqnPad, cqnVan };
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
function cvnToCqnAndCvss(word) {
|
| 61 |
+
if (!word) return { cqn: word, cvn: word, cvss: word };
|
| 62 |
+
const lowerWord = word.toLowerCase();
|
| 63 |
+
let consonant = "", vowelPart = lowerWord, cqnConsonant = "", cqnResult = "", cvnResult = "", cvssResult = "";
|
| 64 |
+
|
| 65 |
+
for (const c of consonants.cvn) {
|
| 66 |
+
if (lowerWord.startsWith(c)) {
|
| 67 |
+
consonant = c;
|
| 68 |
+
cqnConsonant = consonants.cqn[consonants.cvn.indexOf(c)];
|
| 69 |
+
vowelPart = lowerWord.replace(c, "");
|
| 70 |
+
break;
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
const vowelIndex = vowels.cvn.indexOf(vowelPart);
|
| 74 |
+
if (vowelIndex !== -1) {
|
| 75 |
+
cqnResult = vowels.cqn[vowelIndex];
|
| 76 |
+
cvnResult = vowelPart;
|
| 77 |
+
cvssResult = vowels.cvss[vowelIndex];
|
| 78 |
+
} else {
|
| 79 |
+
cqnResult = vowelPart;
|
| 80 |
+
cvnResult = vowelPart;
|
| 81 |
+
cvssResult = vowelPart;
|
| 82 |
+
}
|
| 83 |
+
if (consonant === "j" && vowelPart === "ịa") { cqnConsonant = "gi"; cqnResult = "ỵa"; }
|
| 84 |
+
|
| 85 |
+
const adjusted = adjustConsonantVowel(cqnConsonant, cqnResult);
|
| 86 |
+
cqnConsonant = adjusted.cqnPad;
|
| 87 |
+
cqnResult = adjusted.cqnVan;
|
| 88 |
+
|
| 89 |
+
let cqnOutput = cqnConsonant + cqnResult;
|
| 90 |
+
if (word[0] !== word[0].toLowerCase()) { cqnOutput = cqnOutput.charAt(0).toUpperCase() + cqnOutput.slice(1); }
|
| 91 |
+
if (isUpperCase(word)) { cqnOutput = cqnOutput.toUpperCase(); }
|
| 92 |
+
|
| 93 |
+
return { cqn: cqnOutput, cvn: consonant + cvnResult, cvss: consonant + cvssResult };
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
return {
|
| 97 |
+
cvnToCqn: cvnToCqnAndCvss,
|
| 98 |
+
specialChars
|
| 99 |
+
};
|
| 100 |
+
})();
|
| 101 |
+
|
| 102 |
+
/* ========================================================================== */
|
| 103 |
+
/* PHẦN 2: VIETUNI LIBRARY (MODERNIZED & BRIDGED) */
|
| 104 |
+
/* ========================================================================== */
|
| 105 |
+
|
| 106 |
+
var supported = (document.all || document.getElementById);
|
| 107 |
+
var disabled = false;
|
| 108 |
+
var keymodeid = 4;
|
| 109 |
+
var linebreak = 0;
|
| 110 |
+
var theTyper = null;
|
| 111 |
+
var cvnssMode = false;
|
| 112 |
+
|
| 113 |
+
reset = function(){}
|
| 114 |
+
initTyper = telexingVietUC;
|
| 115 |
+
|
| 116 |
+
function setTypingMode(mode) {
|
| 117 |
+
keymodeid = mode;
|
| 118 |
+
if (mode === 5) {
|
| 119 |
+
cvnssMode = true;
|
| 120 |
+
if (theTyper) theTyper.keymode = new CVKOff();
|
| 121 |
+
} else {
|
| 122 |
+
cvnssMode = false;
|
| 123 |
+
if (theTyper) theTyper.keymode = initKeys();
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
initCharMap = function() { return new CVietUniCodeMap(); }
|
| 128 |
+
|
| 129 |
+
initKeys = function() {
|
| 130 |
+
switch (keymodeid) {
|
| 131 |
+
case 1: return new CTelexKeys();
|
| 132 |
+
case 2: return new CVniKeys();
|
| 133 |
+
case 3: return new CViqrKeys();
|
| 134 |
+
case 4: return new CAllKeys();
|
| 135 |
+
default: return new CVKOff();
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
function telexingVietUC (txtarea, nextfunc) {
|
| 140 |
+
txtarea.vietarea= true;
|
| 141 |
+
txtarea.onkeyup = nextfunc;
|
| 142 |
+
if (!supported) return;
|
| 143 |
+
|
| 144 |
+
// FIXED: Sử dụng onkeydown cho Space và Punctuation để xử lý trước khi ký tự được in ra
|
| 145 |
+
txtarea.onkeydown = function(evt) {
|
| 146 |
+
if (cvnssMode) {
|
| 147 |
+
return handleCVNSSKeyDown(evt, this);
|
| 148 |
+
}
|
| 149 |
+
return onKeyDown(evt);
|
| 150 |
+
};
|
| 151 |
+
|
| 152 |
+
// Legacy support
|
| 153 |
+
txtarea.onkeypress = function(evt) {
|
| 154 |
+
if (!cvnssMode) return vietTyping.call(this, evt);
|
| 155 |
+
};
|
| 156 |
+
|
| 157 |
+
txtarea.getCurrentWord= getCurrentWord;
|
| 158 |
+
txtarea.replaceWord= replaceWord;
|
| 159 |
+
txtarea.onmousedown= onMouseDown;
|
| 160 |
+
if(!theTyper) theTyper = new CVietString("");
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
/**
|
| 164 |
+
* FIXED: LOGIC XỬ LÝ CVNSS CHUYÊN NGHIỆP
|
| 165 |
+
* Bắt sự kiện Space/Enter/Dấu câu để convert từ ngay trước con trỏ
|
| 166 |
+
*/
|
| 167 |
+
function handleCVNSSKeyDown(evt, txtarea) {
|
| 168 |
+
var code = evt.keyCode || evt.which;
|
| 169 |
+
var char = evt.key; // Modern browsers
|
| 170 |
+
|
| 171 |
+
// Nếu bấm Space (32) hoặc Enter (13) hoặc các ký tự đặc biệt
|
| 172 |
+
if (code === 32 || code === 13 || CVNSSConverter.specialChars.includes(char)) {
|
| 173 |
+
|
| 174 |
+
// 1. Lấy từ ngay trước con trỏ
|
| 175 |
+
var wordInfo = getLastWordBeforeCaret(txtarea);
|
| 176 |
+
|
| 177 |
+
if (wordInfo && wordInfo.word.length > 0) {
|
| 178 |
+
// 2. Thử convert
|
| 179 |
+
var result = CVNSSConverter.cvnToCqn(wordInfo.word);
|
| 180 |
+
|
| 181 |
+
// 3. Nếu có sự thay đổi (convert thành công)
|
| 182 |
+
if (result.cqn !== wordInfo.word) {
|
| 183 |
+
// Thay thế từ cũ bằng từ mới
|
| 184 |
+
replaceRange(txtarea, wordInfo.start, wordInfo.end, result.cqn);
|
| 185 |
+
// Sau đó để mặc định trình duyệt in dấu space/enter/dấu câu ra
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
return true; // Luôn cho phép phím hoạt động bình thường
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
/**
|
| 193 |
+
* FIXED: Hàm lấy từ hiện đại, chính xác theo vị trí con trỏ
|
| 194 |
+
*/
|
| 195 |
+
function getLastWordBeforeCaret(el) {
|
| 196 |
+
var end = el.selectionStart;
|
| 197 |
+
if (end === 0) return null;
|
| 198 |
+
|
| 199 |
+
var text = el.value;
|
| 200 |
+
var start = end - 1;
|
| 201 |
+
|
| 202 |
+
// Lùi lại cho đến khi gặp khoảng trắng hoặc dấu câu hoặc đầu dòng
|
| 203 |
+
while (start >= 0) {
|
| 204 |
+
var c = text.charAt(start);
|
| 205 |
+
if (/\s|[\.,;?!]/.test(c)) {
|
| 206 |
+
break;
|
| 207 |
+
}
|
| 208 |
+
start--;
|
| 209 |
+
}
|
| 210 |
+
start++; // Đẩy lên 1 vị trí sau khoảng trắng
|
| 211 |
+
|
| 212 |
+
if (start >= end) return null;
|
| 213 |
+
|
| 214 |
+
return {
|
| 215 |
+
word: text.substring(start, end),
|
| 216 |
+
start: start,
|
| 217 |
+
end: end
|
| 218 |
+
};
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
/**
|
| 222 |
+
* FIXED: Hàm thay thế text an toàn cho trình duyệt hiện đại
|
| 223 |
+
*/
|
| 224 |
+
function replaceRange(el, start, end, newText) {
|
| 225 |
+
if (el.setRangeText) {
|
| 226 |
+
el.setRangeText(newText, start, end, 'end');
|
| 227 |
+
} else {
|
| 228 |
+
// Fallback cũ
|
| 229 |
+
var val = el.value;
|
| 230 |
+
el.value = val.substring(0, start) + newText + val.substring(end);
|
| 231 |
+
el.selectionStart = el.selectionEnd = start + newText.length;
|
| 232 |
+
}
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
// --- CÁC HÀM CŨ CỦA VIETUNI (GIỮ NGUYÊN CHO MODE 1,2,3) ---
|
| 236 |
+
|
| 237 |
+
function getEvt(evt) {
|
| 238 |
+
if (typeof(evt)=='string') return evt.charCodeAt(0);
|
| 239 |
+
return document.all? event.keyCode: (evt && evt.which)? evt.which: 0;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
function onKeyDown(evt) {
|
| 243 |
+
var c= getEvt(evt);
|
| 244 |
+
if ((c==10) || (c==13)) { reset(1); linebreak= 1; }
|
| 245 |
+
else if ((c<49) && (c!=16) && (c!=20)) { linebreak= 0; reset(c==32); }
|
| 246 |
+
return true;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
function onMouseDown(evt) { reset(0); linebreak= 0; return true; }
|
| 250 |
+
|
| 251 |
+
function vietTyping(evt) {
|
| 252 |
+
var c= getEvt(evt);
|
| 253 |
+
theTyper.value= this.getCurrentWord();
|
| 254 |
+
var changed= ((c>32) && theTyper.typing(c));
|
| 255 |
+
if (changed) this.replaceWord(theTyper.value);
|
| 256 |
+
return !changed;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
function getCurrentWord() {
|
| 260 |
+
if(!document.all) return this.value;
|
| 261 |
+
var caret = this.document.selection.createRange();
|
| 262 |
+
if (caret.text) return null;
|
| 263 |
+
var backward = -10;
|
| 264 |
+
do {
|
| 265 |
+
var caret2 = caret.duplicate();
|
| 266 |
+
caret2.moveStart("character", backward++);
|
| 267 |
+
} while (caret2.parentElement() != this && backward <0);
|
| 268 |
+
this.curword = caret2.duplicate();
|
| 269 |
+
return caret2.text;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
function replaceWord(newword) {
|
| 273 |
+
if(!document.all) { this.value= newword; return; }
|
| 274 |
+
this.curword.text = newword;
|
| 275 |
+
this.curword.collapse(false);
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
// "class": CVietString
|
| 279 |
+
function CVietString(str) {
|
| 280 |
+
this.value= str;
|
| 281 |
+
this.keymode= initKeys();
|
| 282 |
+
this.charmap= initCharMap();
|
| 283 |
+
this.ctrlchar= '-';
|
| 284 |
+
this.changed= 0;
|
| 285 |
+
this.typing= typing;
|
| 286 |
+
this.Compose= Compose;
|
| 287 |
+
this.Correct= Correct;
|
| 288 |
+
this.findCharToChange= findCharToChange;
|
| 289 |
+
return this;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
function typing(ctrl) {
|
| 293 |
+
this.changed = 0;
|
| 294 |
+
this.ctrlchar = String.fromCharCode(ctrl);
|
| 295 |
+
if (linebreak) linebreak= 0; else this.keymode.getAction(this);
|
| 296 |
+
this.Correct();
|
| 297 |
+
return this.changed;
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
function Compose(type) {
|
| 301 |
+
if(!this.value) return;
|
| 302 |
+
var info = this.findCharToChange(type);
|
| 303 |
+
if (!info || !info[0]) return;
|
| 304 |
+
var telex;
|
| 305 |
+
if (info[0]=='\\') telex= [1,this.ctrlchar,1];
|
| 306 |
+
else if (type>6) telex= this.charmap.getAEOWD(info[0], type, info[3]);
|
| 307 |
+
else telex= this.charmap.getDau(info[0], type);
|
| 308 |
+
if (!(this.changed = telex[0])) return;
|
| 309 |
+
this.value = this.value.replaceAt(info[1],telex[1],info[2]);
|
| 310 |
+
if (!telex[2]) { spellerror= 1; this.value+= this.ctrlchar; }
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
function Correct() {
|
| 314 |
+
if (this.charmap.maxchrlen || !document.all) return 0;
|
| 315 |
+
var tmp= this.value;
|
| 316 |
+
if ('nNcC'.indexOf(this.ctrlchar)>=0) tmp+= this.ctrlchar;
|
| 317 |
+
var er= /[^\x01-\x7f](hn|hc|gn)$/i.exec(tmp);
|
| 318 |
+
if (er) {
|
| 319 |
+
this.value= tmp.substring(0,tmp.length-2)+er[1].charAt(1)+er[1].charAt(0);
|
| 320 |
+
this.changed= 1;
|
| 321 |
+
}
|
| 322 |
+
else if(!this.changed) return 0;
|
| 323 |
+
er= /\w([^\x01-\x7f])(\w*)([^\x01-\x7f])\S*$/.exec(this.value);
|
| 324 |
+
if (!er) return 0;
|
| 325 |
+
var i= this.charmap.isVowel(er[1]);
|
| 326 |
+
var ri= (i-1)%24 + 1, ci= (i-ri)/24;
|
| 327 |
+
var i2= this.charmap.isVowel(er[3]);
|
| 328 |
+
if (!ci || !i2) return 0;
|
| 329 |
+
var ri2= (i2-1)%24 + 1, ci2= (i2-ri2)/24;
|
| 330 |
+
var nc= this.charmap.charAt(ri)+ er[2]+ this.charmap.charAt(ci*24+ri2);
|
| 331 |
+
this.value= this.value.replace(new RegExp(er[1]+er[2]+er[3],'g'), nc);
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
function findCharToChange(type) {
|
| 335 |
+
var lastchars= this.charmap.lastCharsOf(this.value, 5);
|
| 336 |
+
var i= 0, c=lastchars[0][0], chr=0;
|
| 337 |
+
if (c=='\\') return [c,this.value.length-1,1];
|
| 338 |
+
if (type==15) while (!(chr=this.charmap.isVD(c))) {
|
| 339 |
+
if ((c < 'A') || (i>=4) || !(c=lastchars[++i][0])) return null;
|
| 340 |
+
}
|
| 341 |
+
else while( "cghmnptCGHMNPT".indexOf(c)>=0) {
|
| 342 |
+
if ((c < 'A') || (i>=2) || !(c=lastchars[++i][0])) return null;
|
| 343 |
+
}
|
| 344 |
+
c = lastchars[0][0].toLowerCase();
|
| 345 |
+
var pc = lastchars[1][0].toLowerCase();
|
| 346 |
+
var ppc = lastchars[2][0].toLowerCase();
|
| 347 |
+
if (i==0 && type!=15) {
|
| 348 |
+
if ( (chr=this.charmap.isVowel(lastchars[1][0]))
|
| 349 |
+
&& ("uyoia".indexOf(c)>=0) && !this.charmap.isUO(pc,c)
|
| 350 |
+
&& !((pc=='o' && c=='a') || (pc=='u' && c=='y'))
|
| 351 |
+
&& !((ppc=='q' && pc=='u') || (ppc=='g' && pc=='i')) ) ++i;
|
| 352 |
+
if (c=='a' && (type==9 || type==7)) i= 0;
|
| 353 |
+
}
|
| 354 |
+
c= lastchars[i][0];
|
| 355 |
+
if ((i==0 || chr==0) && type!=15) chr= this.charmap.isVowel(c);
|
| 356 |
+
if (!chr) return null;
|
| 357 |
+
var clen= lastchars[i][1], isuo=0;
|
| 358 |
+
if ((i>0) && (type==7 || type==8 || type==11)) {
|
| 359 |
+
isuo=this.charmap.isUO(lastchars[i+1][0],c);
|
| 360 |
+
if (isuo) { chr=isuo; clen+=lastchars[++i][1]; isuo=1; }
|
| 361 |
+
}
|
| 362 |
+
var pos= this.value.length;
|
| 363 |
+
for (var j=0; j<= i; j++) pos -= lastchars[j][1];
|
| 364 |
+
return [chr, pos, clen, isuo];
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
function CVietCharMap(){
|
| 368 |
+
this.vietchars = null;
|
| 369 |
+
this.length = 149;
|
| 370 |
+
this.chr_cache = new Array(20);
|
| 371 |
+
this.ind_cache = new Array(20);
|
| 372 |
+
this.cptr = 0;
|
| 373 |
+
this.caching= function(chr, ind) {
|
| 374 |
+
this.chr_cache[this.cptr] = chr;
|
| 375 |
+
this.ind_cache[this.cptr++] = ind;
|
| 376 |
+
this.cptr %= 20;
|
| 377 |
+
}
|
| 378 |
+
return this;
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
CVietCharMap.prototype.charAt= function(ind){
|
| 382 |
+
var chrcode = this.vietchars[ind];
|
| 383 |
+
return chrcode ? String.fromCharCode(chrcode) : null;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
CVietCharMap.prototype.isVowel= function(chr){
|
| 387 |
+
var i = 0;
|
| 388 |
+
while ((i<20) && (chr != this.chr_cache[i])) ++i;
|
| 389 |
+
if (i<20) return this.ind_cache[i];
|
| 390 |
+
|
| 391 |
+
i = this.length-5;
|
| 392 |
+
while ((chr != this.charAt(i)) && i) --i;
|
| 393 |
+
this.caching(chr, i);
|
| 394 |
+
return i;
|
| 395 |
+
}
|
| 396 |
+
|
| 397 |
+
CVietCharMap.prototype.isVD= function (chr){
|
| 398 |
+
var ind = this.length-5;
|
| 399 |
+
while ((chr != this.charAt(ind)) && (ind < this.length)) ++ind;
|
| 400 |
+
return (ind<this.length)? ind: 0;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
CVietCharMap.prototype.isUO= function (c1, c2){
|
| 404 |
+
if (!c1 || !c2) return 0;
|
| 405 |
+
var ind1 = this.isVowel(c1);
|
| 406 |
+
var ci = (ind1-1)%12;
|
| 407 |
+
if ((ci!=9) && (ci!=10)) return 0;
|
| 408 |
+
var ind2 = this.isVowel(c2);
|
| 409 |
+
ci = (ind2-1)%12;
|
| 410 |
+
if ((ci!=6) && (ci!=7) && (ci!=8)) return 0;
|
| 411 |
+
return [ind1,ind2];
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
CVietCharMap.prototype.getDau= function (ind, type){
|
| 415 |
+
var accented= (ind < 25)? 0: 1;
|
| 416 |
+
var ind_i= (ind-1) % 24 +1;
|
| 417 |
+
var charset= (type == 6)? 0 : type;
|
| 418 |
+
if ((type== 6) && !accented) return [0];
|
| 419 |
+
var newind= charset*24 + ind_i;
|
| 420 |
+
if (newind == ind) newind= ind_i;
|
| 421 |
+
var chr= this.charAt(newind);
|
| 422 |
+
if (!chr) chr= this.lowerCaseOf(0,newind);
|
| 423 |
+
return [1, chr, newind>24 || type==6];
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
var map=[
|
| 427 |
+
[7,7,7,8,8, 8,9,10,11,15],
|
| 428 |
+
[0,3,6,0,6, 9,0, 3, 6, 0],
|
| 429 |
+
[1,4,7,2,8,10,1, 4, 7, 1]
|
| 430 |
+
];
|
| 431 |
+
CVietCharMap.prototype.getAEOWD= function(ind, type, isuo) {
|
| 432 |
+
var c=0, i1=isuo? ind[0]: ind;
|
| 433 |
+
var vc1= (type==15)? (i1-1)%2 : (i1-1)%12;
|
| 434 |
+
if (isuo) {
|
| 435 |
+
var base= ind[1]-(ind[1]-1)%12;
|
| 436 |
+
if (type==7 || type==11) c= this.charAt(i1-vc1+9)+this.charAt(base+7);
|
| 437 |
+
else if (type==8) c= this.charAt(i1-vc1+10)+this.charAt(base+8);
|
| 438 |
+
return [c!=0, c, 1];
|
| 439 |
+
}
|
| 440 |
+
var i= -1, shift= 0, del= 0;
|
| 441 |
+
while (shift==0 && ++i<map[0].length) {
|
| 442 |
+
if (map[0][i]==type) {
|
| 443 |
+
if(map[1][i]==vc1) shift= map[2][i]-vc1;
|
| 444 |
+
else if(map[2][i]==vc1) shift= map[1][i]-vc1;
|
| 445 |
+
}
|
| 446 |
+
}
|
| 447 |
+
if (shift==0) {
|
| 448 |
+
if (type==7 && (vc1==2 || vc1==8)) shift=-1;
|
| 449 |
+
else if ((type==9 && vc1==2) || (type==11 && vc1==8)) shift=-1;
|
| 450 |
+
else if (type==8 && (vc1==1 || vc1==7)) shift=1;
|
| 451 |
+
del= 1;
|
| 452 |
+
} else del=(shift>0);
|
| 453 |
+
i1 += shift;
|
| 454 |
+
var chr= this.charAt(i1);
|
| 455 |
+
if (i1<145) this.caching(chr, i1);
|
| 456 |
+
if (!chr) chr= this.lowerCaseOf(0, i1);
|
| 457 |
+
return [shift!=0, chr, del];
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
CVietCharMap.prototype.lastCharsOf= function(str, num){
|
| 461 |
+
if (!num) return [str.charAt(str.length-1),1];
|
| 462 |
+
var vchars = new Array(num);
|
| 463 |
+
for (var i=0; i< num; i++) { vchars[i]= [str.charAt(str.length-i-1),1]; }
|
| 464 |
+
return vchars;
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
String.prototype.replaceAt= function(i,newchr,clen){
|
| 468 |
+
return this.substring(0,i)+ newchr + this.substring(i+clen);
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
function CVietUniCodeMap(){ var map= new CVietCharMap();
|
| 472 |
+
map.vietchars = new Array(
|
| 473 |
+
"UNICODE",
|
| 474 |
+
97, 226, 259, 101, 234, 105, 111, 244, 417, 117, 432, 121,
|
| 475 |
+
65, 194, 258, 69, 202, 73, 79, 212, 416, 85, 431, 89,
|
| 476 |
+
225, 7845, 7855, 233, 7871, 237, 243, 7889, 7899, 250, 7913, 253,
|
| 477 |
+
193, 7844, 7854, 201, 7870, 205, 211, 7888, 7898, 218, 7912, 221,
|
| 478 |
+
224, 7847, 7857, 232, 7873, 236, 242, 7891, 7901, 249, 7915, 7923,
|
| 479 |
+
192, 7846, 7856, 200, 7872, 204, 210, 7890, 7900, 217, 7914, 7922,
|
| 480 |
+
7841, 7853, 7863, 7865, 7879, 7883, 7885, 7897, 7907, 7909, 7921, 7925,
|
| 481 |
+
7840, 7852, 7862, 7864, 7878, 7882, 7884, 7896, 7906, 7908, 7920, 7924,
|
| 482 |
+
7843, 7849, 7859, 7867, 7875, 7881, 7887, 7893, 7903, 7911, 7917, 7927,
|
| 483 |
+
7842, 7848, 7858, 7866, 7874, 7880, 7886, 7892, 7902, 7910, 7916, 7926,
|
| 484 |
+
227, 7851, 7861, 7869, 7877, 297, 245, 7895, 7905, 361, 7919, 7929,
|
| 485 |
+
195, 7850, 7860, 7868, 7876, 296, 213, 7894, 7904, 360, 7918, 7928,
|
| 486 |
+
100, 273, 68, 272);
|
| 487 |
+
return map;
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
function CVietKeys() {
|
| 491 |
+
this.getAction= function(typer){
|
| 492 |
+
var i= this.keys.indexOf(typer.ctrlchar.toLowerCase());
|
| 493 |
+
if(i>=0) typer.Compose(this.actions[i]);
|
| 494 |
+
}
|
| 495 |
+
return this;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
function CVKOff() {
|
| 499 |
+
this.off = true;
|
| 500 |
+
this.getAction= function(){};
|
| 501 |
+
return this;
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
function CTelexKeys() {
|
| 505 |
+
var k= new CVietKeys();
|
| 506 |
+
k.keys= "sfjrxzaeowd";
|
| 507 |
+
k.actions= [1,2,3,4,5,6,9,10,11,8,15];
|
| 508 |
+
k.istelex= true;
|
| 509 |
+
return k;
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
function CVniKeys() {
|
| 513 |
+
var k= new CVietKeys();
|
| 514 |
+
k.keys= "0123456789";
|
| 515 |
+
k.actions= [6,1,2,4,5,3,7,8,8,15];
|
| 516 |
+
return k;
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
function CViqrKeys() {
|
| 520 |
+
var k= new CVietKeys();
|
| 521 |
+
k.keys= "\xB4'\u2019`.?~-^(*+d";
|
| 522 |
+
k.actions= [1,1,1,2,3,4,5,6,7,8,8,8,15];
|
| 523 |
+
return k;
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
function CAllKeys() {
|
| 527 |
+
var k= new CVietKeys();
|
| 528 |
+
k.keys= "sfjrxzaeowd0123456789\xB4'`.?~-^(*+d";
|
| 529 |
+
k.actions= [1,2,3,4,5,6,9,10,11,8,15,6,1,2,4,5,3,7,8,8,15,1,1,2,3,4,5,6,7,8,8,8,15];
|
| 530 |
+
k.istelex= true;
|
| 531 |
+
return k;
|
| 532 |
+
}
|