Giải pháp Free gõ tiếng Việt Telex,VNI,VIQR cho iPad

Thảo luận trong 'Tặng phần mềm cho iPad' bắt đầu bởi thuannp, 10/5/10.

  1. thuannp

    thuannp Thành viên

    Thân chào

    Hiện tại theo tôi biết thì Ipad có 2 cách để gõ tiếng Việt:
    1 là sử dụng các phần mềm gõ TV mua trên itunes như .VN: nhược điểm là phải mất phí, phải mua tài khoản ...
    2 là bật một trang web có hỗ trợ gõ tiếng việt lên và type sau đó copy, paste. Nhược điểm là phải có mạng wifi thì mới làm được.

    Tôi rất trông đợi một bộ gõ tiếng việt tích hợp trực tiếp trên keyboard để anh em có thể type ngay tại từng ứng dụng, cái này thì phải chờ vietnamese developer thôi.

    Trong thời gian chờ đợi tôi đã tìm ra 1 phương pháp khắc phục được nhược điểm của 2 cách hiện tại. Đó là sử dụng js (javascript).

    Cách thức thực hiện như sau:
    1. Copy toàn bộ đoạn code dưới đây vào Notepad, save lại thành file Unikey.htm (lưu ý khi save phần Save as type chọn All Type)
    2. Sync file này vào Ipad qua các phần mềm hỗ trợ đọc htm. Tôi đã test ok trên ReaddleDocs và GoodReader.
    3. Mở file này ra và gõ tiếng việt rất chuẩn. Gõ xong thì copy và paste thôi.

    Tôi đã thử làm 1 button Select All và Copy All để copy nhanh nội dung bằng javascript nhưng chạy trên IE ở win7 thì OK, FF cũng ok nhưng đưa vào ipad thì ko hoạt động được. Bro nào thạo js thử nghiên cứu cùng tôi để phát triển ứng dụng này.

    Ngoài ra tôi cũng đang tìm cách mở ứng dụng này bằng safari nhưng cũng chưa thành công. Nếu mở được thì sử dụng kèm với 1 app browser hỗ trợ 2 cửa sổ web là có thể type và paste khá dễ dàng. Hy vọng bro nào đó tiếp tục nghiên cứu theo hướng này và share cho ae

    Bắt đầu copy từ đây:

    Lưu ý: đã có bản cập nhật cho phép gõ tiếng việt telex, vni và viqr, xin xem bài của tôi ở trang 3


    Code:
    
    <html>
    
    <head>
    <meta name="GENERATOR" content="Microsoft FrontPage 5.0">
    <meta name="ProgId" content="FrontPage.Editor.Document">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unikey</title>
    </head>
    
    <body onload="setTypingMode(1);" bgcolor="#FFFFCC">
    
    <form name="myform" id="myform">
    <textarea name="holdtext" id="holdtext" rows="38" cols="66" style="font-family:Arial; font-size:25px;" onKeyUp="initTyper(this);"></textarea>
    </form>
    
    
    <script language="JavaScript1.2" type="text/javascript">
    var supported = (document.all || document.getElementById);
    var disabled = false;
    var charmapid = 1;
    var keymodeid = 0;
    var linebreak = 0;
    var theTyper = null;
    
    reset = function(){}
    initTyper = telexingVietUC;
    
    function setTypingMode(mode) {
      keymodeid = mode;
      if (theTyper) theTyper.keymode= initKeys();
      if (!supported && !disabled) {
        alert("Xin loi, trinh duyet web cua ban khong cho phep dung VietTyping.\n");
        disabled = true;
      }
    }
    
    initCharMap = function() { return new CVietUniCodeMap(); }
    
    initKeys = function() {
      switch (keymodeid) {
        case 1: return new CTelexKeys();
        case 2: return new CVniKeys();
        case 3: return new CViqrKeys();
        case 4: return new CAllKeys();
        default: return new CVKOff();
      }
    }
    
    function telexingVietUC (txtarea) {
      txtarea.vietarea= true;
      txtarea.onkeyup= null;
      if (!supported) return;
      txtarea.onkeypress= vietTyping;
      txtarea.getCurrentWord= getCurrentWord;
      txtarea.replaceWord= replaceWord;
      txtarea.onkeydown= onKeyDown;
      txtarea.onmousedown= onMouseDown;
      if(!theTyper) theTyper = new CVietString("");
    }
    
    function getEvt(evt) {
      if (typeof(evt)=='string') return evt.charCodeAt(0);
      return document.all? event.keyCode: (evt && evt.which)? evt.which: 0;
    }
    
    function onKeyDown(evt) {
      var c= getEvt(evt);
      if ((c==10) || (c==13)) { reset(1); linebreak= 1; }
      else if ((c<49) && (c!=16) && (c!=20)) { linebreak= 0; reset(c==32); }
      return true;
    }
    
    function onMouseDown(evt) { reset(0); linebreak= 0; return true; }
    
    function vietTyping(evt) {
      var c= getEvt(evt);
      theTyper.value= this.getCurrentWord();
      var changed= ((c>32) && theTyper.typing(c));
      if (changed) this.replaceWord(theTyper.value);
      return !changed;
    }
    
    function getCurrentWord() {
      if(!document.all) return this.value;
      var caret = this.document.selection.createRange();
      if (caret.text) return null;
      var backward = -10;
      do {
        var caret2 = caret.duplicate();
        caret2.moveStart("character", backward++);
      } while (caret2.parentElement() != this && backward <0);
      this.curword = caret2.duplicate();
      return caret2.text;
    }
    
    function replaceWord(newword) {
      if(!document.all) { this.value= newword; return; }
      this.curword.text = newword;
      this.curword.collapse(false);
    }
    // end interface
    
    
    // "class": CVietString
    //
    function CVietString(str) {
      this.value= str;
      this.keymode= initKeys();
      this.charmap= initCharMap();
      this.ctrlchar= '-';
      this.changed= 0;
    
      this.typing= typing;
      this.Compose= Compose;
      this.Correct= Correct;
      this.findCharToChange= findCharToChange;
      return this;
    }
    
    function typing(ctrl) {
      this.changed = 0;
      this.ctrlchar = String.fromCharCode(ctrl);
      if (linebreak) linebreak= 0; else this.keymode.getAction(this);
      this.Correct();
      return this.changed;
    }
    
    function Compose(type) {
      if(!this.value) return;
      var info = this.findCharToChange(type);
      if (!info || !info[0]) return;
      var telex;
      if (info[0]=='\\') telex= [1,this.ctrlchar,1];
      else if (type>6) telex= this.charmap.getAEOWD(info[0], type, info[3]);
      else telex= this.charmap.getDau(info[0], type);
      if (!(this.changed = telex[0])) return;
      this.value = this.value.replaceAt(info[1],telex[1],info[2]);
      if (!telex[2]) { spellerror= 1; this.value+= this.ctrlchar; }
    }
    
    function Correct() {
      if (this.charmap.maxchrlen || !document.all) return 0;
      var tmp= this.value;
      if ('nNcC'.indexOf(this.ctrlchar)>=0) tmp+= this.ctrlchar;
      var er= /[^\x01-\x7f](hn|hc|gn)$/i.exec(tmp);
      if (er) {
        this.value= tmp.substring(0,tmp.length-2)+er[1].charAt(1)+er[1].charAt(0);
        this.changed= 1;
      }
      else if(!this.changed) return 0;
      er= /\w([^\x01-\x7f])(\w*)([^\x01-\x7f])\S*$/.exec(this.value);
      if (!er) return 0;
      var i= this.charmap.isVowel(er[1]);
      var ri= (i-1)%24 + 1, ci= (i-ri)/24;
      var i2= this.charmap.isVowel(er[3]);
      if (!ci || !i2) return 0;
      var ri2= (i2-1)%24 + 1, ci2= (i2-ri2)/24;
      var nc= this.charmap.charAt(ri)+ er[2]+ this.charmap.charAt(ci*24+ri2);
      this.value= this.value.replace(new RegExp(er[1]+er[2]+er[3],'g'), nc);
    }
    
    function findCharToChange(type) {
      var lastchars= this.charmap.lastCharsOf(this.value, 5);
      var i= 0, c=lastchars[0][0], chr=0;
      if (c=='\\') return [c,this.value.length-1,1];
      if (type==15) while (!(chr=this.charmap.isVD(c))) {
        if ((c < 'A') || (i>=4) || !(c=lastchars[++i][0])) return null;
      }
      else while( "cghmnptCGHMNPT".indexOf(c)>=0) {
        if ((c < 'A') || (i>=2) || !(c=lastchars[++i][0])) return null;
      }
      c = lastchars[0][0].toLowerCase();
      var pc = lastchars[1][0].toLowerCase();
      var ppc = lastchars[2][0].toLowerCase();
      if (i==0 && type!=15) {
        if ( (chr=this.charmap.isVowel(lastchars[1][0]))
          && ("uyoia".indexOf(c)>=0) && !this.charmap.isUO(pc,c)
          && !((pc=='o' && c=='a') || (pc=='u' && c=='y'))
          && !((ppc=='q' && pc=='u') || (ppc=='g' && pc=='i')) ) ++i;
        if (c=='a' && (type==9 || type==7)) i= 0;
      }
      c= lastchars[i][0];
      if ((i==0 || chr==0) && type!=15) chr= this.charmap.isVowel(c);
      if (!chr) return null;
      var clen= lastchars[i][1], isuo=0;
      if ((i>0) && (type==7 || type==8 || type==11)) {
        isuo=this.charmap.isUO(lastchars[i+1][0],c);
        if (isuo) { chr=isuo; clen+=lastchars[++i][1]; isuo=1; }
      }
      var pos= this.value.length;
      for (var j=0; j<= i; j++) pos -= lastchars[j][1];
      return [chr, pos, clen, isuo];
    }
    // end CVietString
    
    
    // character-map template
    //
    function CVietCharMap(){
      this.vietchars = null;
      this.length = 149;
      this.chr_cache = new Array(20);
      this.ind_cache = new Array(20);
      this.cptr = 0;
      this.caching= function(chr, ind) {
        this.chr_cache[this.cptr] = chr;
        this.ind_cache[this.cptr++] = ind;
        this.cptr %= 20;
      }
      return this;
    }
    
    CVietCharMap.prototype.charAt= function(ind){
      var chrcode = this.vietchars[ind];
      return chrcode ? String.fromCharCode(chrcode) : null;
    }
    
    CVietCharMap.prototype.isVowel= function(chr){
      var i = 0;
      while ((i<20) && (chr != this.chr_cache[i])) ++i;
      if (i<20) return this.ind_cache[i];
    
      i = this.length-5;
      while ((chr != this.charAt(i)) && i) --i;
      this.caching(chr, i);
      return i;
    }
    
    CVietCharMap.prototype.isVD= function (chr){
      var ind = this.length-5;
      while ((chr != this.charAt(ind)) && (ind < this.length)) ++ind;
      return (ind<this.length)? ind: 0;
    }
    
    CVietCharMap.prototype.isUO= function (c1, c2){
      if (!c1 || !c2) return 0;
      var ind1 = this.isVowel(c1);
      var ci = (ind1-1)%12;
      if ((ci!=9) && (ci!=10)) return 0;
      var ind2 = this.isVowel(c2);
      ci = (ind2-1)%12;
      if ((ci!=6) && (ci!=7) && (ci!=8)) return 0;
      return [ind1,ind2];
    }
    
    CVietCharMap.prototype.getDau= function (ind, type){
      var accented= (ind < 25)? 0: 1;
      var ind_i= (ind-1) % 24 +1;
      var charset= (type == 6)? 0 : type;
      if ((type== 6) && !accented) return [0];
      var newind= charset*24 + ind_i;
      if (newind == ind) newind= ind_i;
      var chr= this.charAt(newind);
      if (!chr) chr= this.lowerCaseOf(0,newind);
      return [1, chr, newind>24 || type==6];
    }
    
    var map=[
    [7,7,7,8,8, 8,9,10,11,15],
    [0,3,6,0,6, 9,0, 3, 6, 0],
    [1,4,7,2,8,10,1, 4, 7, 1]
    ];
    CVietCharMap.prototype.getAEOWD= function(ind, type, isuo) {
      var c=0, i1=isuo? ind[0]: ind;
      var vc1= (type==15)? (i1-1)%2 : (i1-1)%12;
      if (isuo) {
        var base= ind[1]-(ind[1]-1)%12;
        if (type==7 || type==11) c= this.charAt(i1-vc1+9)+this.charAt(base+7);
        else if (type==8) c= this.charAt(i1-vc1+10)+this.charAt(base+8);
        return [c!=0, c, 1];
      }
      var i= -1, shift= 0, del= 0;
      while (shift==0 && ++i<map[0].length) {
        if (map[0][i]==type) {
          if(map[1][i]==vc1) shift= map[2][i]-vc1;
          else if(map[2][i]==vc1) shift= map[1][i]-vc1;
        }
      }
      if (shift==0) {
        if (type==7 && (vc1==2 || vc1==8)) shift=-1;
        else if ((type==9 && vc1==2) || (type==11 && vc1==8)) shift=-1;
        else if (type==8 && (vc1==1 || vc1==7)) shift=1;
        del= 1;
      } else del=(shift>0);
      i1 += shift;
      var chr= this.charAt(i1);
      if (i1<145) this.caching(chr, i1);
      if (!chr) chr= this.lowerCaseOf(0, i1);
      return [shift!=0, chr, del];
    }
    
    CVietCharMap.prototype.lastCharsOf= function(str, num){
      if (!num) return [str.charAt(str.length-1),1];
      var vchars = new Array(num);
      for (var i=0; i< num; i++) { vchars[i]= [str.charAt(str.length-i-1),1]; }
      return vchars;
    }
    // end CVietCharMap prototype
    
    
    String.prototype.replaceAt= function(i,newchr,clen){
      return this.substring(0,i)+ newchr + this.substring(i+clen);
    }
    
    // output map: class CVietUniCodeMap
    //
    function CVietUniCodeMap(){ var map= new CVietCharMap();
    map.vietchars = new Array(
    "UNICODE",
    97, 226, 259, 101, 234, 105, 111, 244, 417, 117, 432, 121,
    65, 194, 258, 69, 202, 73, 79, 212, 416, 85, 431, 89,
    225, 7845, 7855, 233, 7871, 237, 243, 7889, 7899, 250, 7913, 253,
    193, 7844, 7854, 201, 7870, 205, 211, 7888, 7898, 218, 7912, 221,
    224, 7847, 7857, 232, 7873, 236, 242, 7891, 7901, 249, 7915, 7923,
    192, 7846, 7856, 200, 7872, 204, 210, 7890, 7900, 217, 7914, 7922,
    7841, 7853, 7863, 7865, 7879, 7883, 7885, 7897, 7907, 7909, 7921, 7925,
    7840, 7852, 7862, 7864, 7878, 7882, 7884, 7896, 7906, 7908, 7920, 7924,
    7843, 7849, 7859, 7867, 7875, 7881, 7887, 7893, 7903, 7911, 7917, 7927,
    7842, 7848, 7858, 7866, 7874, 7880, 7886, 7892, 7902, 7910, 7916, 7926,
    227, 7851, 7861, 7869, 7877, 297, 245, 7895, 7905, 361, 7919, 7929,
    195, 7850, 7860, 7868, 7876, 296, 213, 7894, 7904, 360, 7918, 7928,
    100, 273, 68, 272);
    return map;
    }
    
    // input methods: class C...Keys
    function CVietKeys() {
      this.getAction= function(typer){
        var i= this.keys.indexOf(typer.ctrlchar.toLowerCase());
        if(i>=0) typer.Compose(this.actions[i]);
      }
      return this;
    }
    
    function CVKOff() {
      this.off = true;
      this.getAction= function(){};
      return this;
    }
    
    function CTelexKeys() {
      var k= new CVietKeys();
      k.keys= "sfjrxzaeowd";
      k.actions= [1,2,3,4,5,6,9,10,11,8,15];
      k.istelex= true;
      return k;
    }
    
    function CVniKeys() {
      var k= new CVietKeys();
      k.keys= "0123456789";
      k.actions= [6,1,2,4,5,3,7,8,8,15];
      return k;
    }
    
    function CViqrKeys() {
      var k= new CVietKeys();
      k.keys= "\xB4/'\u2019`.?~-^(*+d";
      k.actions= [1,1,1,1,2,3,4,5,6,7,8,8,8,15];
      return k;
    }
    
    function CAllKeys() {
      var k= new CVietKeys();
      k.keys= "sfjrxzaeowd0123456789\xB4/'`.?~-^(*+d";
      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,1,2,3,4,5,6,7,8,8,8,15];
      k.istelex= true;
      return k;
    }
    
    // end vietuni.js
    
    </script>
    
    </body>
    
    </html>
    
    
    
    :
    CrystalShield, nghiemhung, girl_so_fox3 người khác thích nội dung này.
  2. caocaotac

    caocaotac Thành viên mới

    Bạn cho vài hình ảnh xem như thế nào,hiện giờ mình xài Viet free keyboard trên source của iphone.gsm.vn cũng OK.
  3. dannhut

    dannhut Thành viên

    Hay quá... mình sẽ nghiên cứu thêm.. vậy là có cách gõ free mang ý nghĩa cộng đồng rồi.. đúng là từng bước khắc phục khó khăn..
  4. thuannp

    thuannp Thành viên

    Ủa vậy ra ipad jb xong cài app bạn nói là type đc TV trực tiếp từ keyboard à. Mình nghĩ app bạn nói chắc là cho iphone thôi đúng ko. Nếu như vậy thì khi cần type TV cho các app trong bộ iwork hay Notes thì vẫn phải copy paste đúng ko. Nếu như vẫn phải copy paste thì mình nghĩ dùng giải pháp của mình tiện hơn. Vừa ko cần jb, ko mất tiền mua trên appstore vừa đơn giản nhẹ nhàng, support ipad 100%. Giao diện thì cũng chẳng có j đâu chỉ đơn giản là một ô nhập liệu textarea phủ kín toàn màn hình thôi nên mình ko up ảnh chụp lên nữa. Bài post của mình là type từ cái ứng dụng này đấy.
  5. caocaotac

    caocaotac Thành viên mới

    Cái này không phải là app mà chỉ thêm các ký tự vào keyboard,có thể type trực tiếp bất cứ chổ nào và không cần copy,paste gì cả.

    [​IMG]

    [​IMG]
  6. thuannp

    thuannp Thành viên

    À như vậy thì cũng ổn đấy ko phải copy paste chắc tôi cũng phải jb ipad để xài cái này. Tuy nhiên cũng có cái dở là ko type kiểu telex đc điều này sẽ làm giảm tốc độ type. Theo tôi lý tưởng nhất vẫn là dạng keyboard trực tiếp và cho phép gõ telex như vậy type vừa nhanh vừa ko cần copy paste. Ko biết bao giờ mới có app này
  7. caocaotac

    caocaotac Thành viên mới

    Bạn đợi phiên bản 4.0 trên iPad sẽ có bộ gõ telex mặc định luôn.Hiện giờ phiên bản 4.0 dành cho iPhone có có rồi.iPad chắc chờ vài tháng nữa.
  8. nickbakay

    nickbakay Thành viên

    iPad của bác là iPad 4G lun. ^^ :D
  9. tungbao2000

    tungbao2000 Thành viên

    cho mình hỏi IPAD có add fonts Vni được không?
  10. thuannp

    thuannp Thành viên


    Mình đã test thử nhưng ko đc. Có lẽ ipad chỉ hỗ trợ kiểu gõ telex thôi
  11. phanuyvu

    phanuyvu Thành viên

    mình thì không thích JB nên...đành đợi iPad firmware 4.0 vậy.
  12. designxvn

    designxvn Thành viên

    Cái này mình nghī lâu rùi.. Ko kha? thi .
  13. bshieu

    bshieu Thành viên

    Gõ tiếng Việt

    làm sao thêm các ký tự vào keyboard được, bạn chỉ cho minh đi, cảm ơn
  14. designxvn

    designxvn Thành viên

    Đầu tiên jailbreak Ipad.. Sau đó vào Cydia addd souce : iphone.gsm.vn

    Vào install Vietkeyboard !
  15. dynhm

    dynhm Thành viên

    Khi nào mới có gõ tiếng việt telex nhỉ, bây giờ chỉ gõ trên tinh tế được. Hi vọng 1 ngày không xa sẽ có telex để soạn thảo văn bản.
  16. thuannp

    thuannp Thành viên

    Ủa thế bạn đọc bài này của mình mà sao vẫn hỏi như vậy nhỉ ? Thử thực hiện theo hướng dẫn của mình ở trang 1, sẽ tạo ra 1 file là Unikey.htm. Sync vào Ipad với phần mềm Good Reader hoặc ReaddleDocs sẽ gõ được tiếng việt unicode theo kiểu telex một cách hoàn hảo, tương tự như việc gõ tiếng Việt trên tinhte vậy vì cùng một bộ mã hóa unicode như nhau. Sau khi gõ xong thì copy và paste vào ứng dụng mình cần.

    Còn để gõ telex trực tiếp trên bàn phím ảo của Ipad thì đành phải đợi 4.0 thôi.
    daithanhthai thích nội dung này.
  17. dynhm

    dynhm Thành viên

    Hiểu lầm, ý là gõ tiếng việt trực tiếp trong phần mềm soạn thảo hoặc trong Notes đó bạ. Gõ telex như đang gõ trên ipad&tinh tế nè. Thanks nhé!

    ---------- Post added at 07:39 PM ---------- Previous post was at 07:38 PM ----------

    Có thì nhắn tin nhé bạn.
  18. davitru

    davitru Thành viên

    haizz.. có vẻ như vấn đề bộ gõ phức tạp quá nhỉ.. giá mà có Inspell cho ipad như Iphone thì hay biết mấy :|
  19. caochinguyen

    caochinguyen Thành viên

    đã có cách mở ứng dụng của bạn bằng safari ^^! tks đã share, xài telex gõ tiếng việt sướng lắm, gõ bằng cái này rồi copy qua những chỗ khác cho lẹ :)
  20. dannhut

    dannhut Thành viên

    Bạn có thể chia sẻ làm các nào để safari mở được file html có trong iPad?

Chia sẻ trang này