Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/webroot/js/i18n.js

[return to app]
1 /**
2  * Phonetic-Typing System - multilingual forms allow users to easily type characters in other alphabets by
 
pressing the phonetically-equivalent English keys
3  
This file MUST be saved as a UTF-8 text filesaving in Latin or another character set will permanently destroy
 
the character maps.
4  * @
author Eric David Benari
5  
* @link http://www.Vork.us
6  
*/
7  
8  
/**
9  * Activates the i18n system
10  * @param str ids Optional, a string or an array of strings containing the id(s) of form inputs/textareas to
 
enable use of i18n - if omitted all textareas and text-inputs will be i18n activated
11  
*/
12
/* public */ var i18n = function(ids) {
13     
i18n.initialized true;
14     if (
typeof ids != 'undefined') {
15         if (
typeof ids != 'object') {
16             
ids = [ids];
17         }
18         var 
thisid;
19         for (var 
i in ids) {
20             
thisid document.getElementById(ids[i]);
21             if (
thisid) {
22                 
thisid.onkeypress i18n.keyPressed;
23             }
24         }
25     } else {
26         var 
textareas document.body.getElementsByTagName('textarea');
27         for (var 
0textareas.lengthi++) {
28             
textareas[i].onkeypress i18n.keyPressed;
29         }
30         var 
inputs document.body.getElementsByTagName('input');
31         for (var 
0inputs.lengthi++) {
32             if (
inputs[i].type == 'text') {
33                 
inputs[i].onkeypress i18n.keyPressed;
34             }
35         }
36     }
37     if (
typeof i18n.langs == 'undefined') {
38         
i18n.setLanguages();
39     }
40 }
41
42  
/**
43  * Name of the current language
44  * @var string
45  */
46 /* protected */ 
i18n.languageName 'english';
47  
48  
/**
49  * Current language
50  * @var mixed English is a string, other languages are an object
51  */
52 /* protected */ 
i18n.language 'english';
53
54  
/**
55  * Language mappings
56  * @var object
57  */
58 /* protected */ 
i18n.languages = {
59
'russian': {'a':'а''b':'б''c':'ц''d':'д''e':'е''f':'ф''g':'г''h':'ч',
 
'i':'и''j':'ж'
60
'k':'к''l':'л''m':'м''n':'н''o':'о''p':'п''q':'ё''r':'р''s':'с',
 
't':'т''u':'у''v':'в'
61
'w':'ю''x':'х''y':'я''z':'з'
62
'[':'ш'']':'щ'"'":'ь''`':'ъ''=':'й''-':'ы''\\':'э',
63
'A':'А''B':'Б''C':'Ц''D':'Д''E':'Е''F':'Ф''G':'Г''H':'Ч''I':'И',
 
'J':'Ж',
64
'K':'К''L':'Л''M':'М''N':'Н''O':'О''P':'П''Q':'Ё''R':'Р''S':'С',
 
'T':'Т'
65
'U':'У''V':'В''W':'Ю''X':'Х''Y':'Я''Z':'З'
66
'{':'Ш''}':'Щ''"':'Ь''~':'Ъ''+':'Й''_':'Ы',  '|':'Э'},
67
'hebrew': {'a':'א''A':'×¢''b':'ב''B':'ב''c':'כ''C':'ך''d':'ד''D':'ד',
 
'e':'א''E':'ע',
68
'f':'פ''F':'ף''g':'ג''G':'ג''h':'ה''H':'ה''i':'י''I':'י''j':'ג',
 
'J':'ג''k':'ק''K':'ק',
69
'l':'ל''L':'ל''m':'מ''M':'ם''n':'נ''N':'ן''o':'ו''O':'ו''p':'פ',
 
'P':'ף''q':'ח''Q':'ח',
70
'r':'ר''R':'ר''s':'ס''S':'ש''t':'ת''T':'ט''u':'ו''U':'ו''v':'ו',
 
'V':'ו''w':'ו''W':'ו',
71
'x':'צ''X':'ץ''y':'י''Y':'י''z':'ז''Z':'ז'},
72
'arabic': {'a':'ا''A':'ع''b':'ب''B':'ب''c':'ك''C':'ق''d':'د''D':'ض',
73
'e':'إ''E':'أ''f':'ف''F':'ف''g':'غ''G':'غ''h':'ح''H':'ه''i':'ى',
 
'I':'Ø¥',
74
'j':'ج''J':'ظ''k':'ك''K':'ق''l':'ل''L':'ل''m':'م''M':'م''n':'ن',
 
'N':'ن''o':'و''O':'ؤ',
75
'p':'پ''P':'پ''q':'ق''Q':'ك''r':'ر''R':'ر''s':'س''S':'ص''t':'ت',
 
'T':'ط''u':'و''U':'ؤ',
76
'v':'و''V':'ؤ''w':'و''W':'ؤ''x':'خ''X':'خ''y':'ي''Y':'ئ''z':'ذ',
 
'Z':'ز',
77
'1':'Ù¡''2':'Ù¢''3':'Ù£''4':'Ù¤''5':'Ù¥''6':'Ù¦''7':'Ù§''8':'Ù¨''9':'Ù©',
 
'0':'Ù ',
78
"'":'ء''`':'ة''[':'ث''{':'چ'']':'ش''}':'ژ'},
79
'greek': {'a':'α''A':'Α''b':'β''B':'Β''c':'ς''C':'ς''d':'δ''D':'Δ',
80
'e':'ε''E':'Ε''f':'φ''F':'Φ''g':'θ''G':'Θ''h':'χ''H':'Χ''i':'ι',
 
'I':'Ι''j':'θ''J':'Θ'
81
'k':'κ''K':'Κ''l':'λ''L':'Λ''m':'μ''M':'Μ''n':'ν''N':'Ν''o':'ο',
 
'O':'Ο''p':'π''P':'Π',
82
'q':'ψ''Q':'Ψ''r':'ρ''R':'Ρ''s':'σ''S':'Σ''t':'τ''T':'Τ''u':'η',
 
'U':'Η''v':'υ''V':'Υ',
83
'w':'ω''W':'Ω''x':'ξ''X':'Ξ''y':'γ''Y':'Γ''z':'ζ''Z':'Ζ'}
84 }
85
86  
/**
87  * Converts keystrokes pressed to the selected language
88  * @param object evt
89  */
90 /* protected */ 
i18n.keyPressed = function(evt) {
91     if (
typeof evt != 'undefined') {
92         var 
charCode evt.which;
93         var 
chr String.fromCharCode(charCode);
94         if (
i18n.language == 'default' || typeof i18n.language[chr] == 'undefined') {
95             return 
true;
96         }
97         var 
loc this.selectionStart;
98         if (
loc == this.value.length) {
99             
this.value += i18n.language[chr];
100         } else {
101             
this.value this.value.substring(0loc) + i18n.language[chr] +
 
this.value.substring(this.selectionEndthis.value.length);
102             
loc++;
103             
this.setSelectionRange(locloc);
104         }
105         
evt.preventDefault();
106     } else { 
//IE
107         
evt window.event;
108         var 
charCode evt.keyCode;
109         var 
chr String.fromCharCode(charCode);
110         if (
i18n.language == 'default' || typeof i18n.language[chr] == 'undefined') {
111             return 
true;
112         }
113         var 
bookmark document.selection.createRange().getBookmark();
114         var 
selection this.createTextRange();
115         
selection.moveToBookmark(bookmark);
116         var 
before this.createTextRange();
117         
before.collapse(true);
118         
before.setEndPoint("EndToStart"selection);
119         var 
loc before.text.length;
120         if (
loc == this.value.length) {
121             
this.value += i18n.language[chr];
122         } else {
123             var 
end = (loc selection.text.length);
124             
this.value this.value.substring(0loc) + i18n.language[chr] + this.value.substring(end,
 
this.value.length);
125             
loc++;
126             
before.collapse(true)
127             
before.moveStart('character'loc);
128             
before.moveEnd('character'0);
129             
before.select();
130         }
131         return 
false;
132     }
133 }
134
135  
/**
136  * Builds the keyboard display for the selected language
137  */
138 /* protected */ 
i18n.getKeyboardLayout = function() {
139     var 
specialUpper = {'`''~''-':'_''=':'+''[''{'']''}''\\':'|'';':':'"'"'"'}
140     var 
qwerty = [
141         [
'q''w''e''r''t''y''u''i''o''p''['']''\\'],
142         [
'a''s''d''f''g''h''j''k''l'';'"'"],
143         [
'z''x''c''v''b''n''m'', ''.''/']
144     ];
145     var 
margin 13;
146     if (
typeof i18n.language['`'] != 'undefined') {
147         if (
typeof i18n.language['1'] != 'undefined') {
148             
qwerty.unshift(['`''1''2''3''4''5''6''7''8''9''0''-''=']);
149         } else {
150             
qwerty[0].unshift('`');
151             
qwerty[0][qwerty[0].length] = '-';
152             
qwerty[0][qwerty[0].length] = '=';
153         }
154         
margin 48;
155     }
156     var 
keyboard '<div class="keyboardcontainer">';
157     for (var 
row in qwerty) {
158         
keyboard += '<div class="keyboard keyboardrow' row '">';
159         for (var 
chr in qwerty[row]) {
160             if (
typeof i18n.language[qwerty[row][chr]] != 'undefined') {
161                 var 
upper qwerty[row][chr].toUpperCase();
162                 if (
upper == qwerty[row][chr] && typeof specialUpper[upper] != 'undefined') {
163                     
upper specialUpper[upper];
164                 }
165                 if (
upper != qwerty[row][chr] && typeof i18n.language[upper] != 'undefined') {
166                     
keyboard += '<div class="key"><div>' i18n.language[upper] + '<br />' +
 
i18n.language[qwerty[row][chr]] + '</div>' upper '<br />' qwerty[row][chr] + '</div>';
167                 } else {
168                     
keyboard += '<div class="key"><div><br />' i18n.language[qwerty[row][chr]] + '</div><br />'
 
qwerty[row][chr] + '</div>';
169                 }
170             }
171         }
172         
keyboard += '</div>';
173     }
174     
keyboard += '</div>';
175     if (
typeof i18n.css == 'undefined') {
176         
i18n.css '.keyboardcontainer {margin-top: 5px;}\n '
177             
'.keyboard {clear: left;}\n '
178             
'.keyboardrow1 {margin-left: ' margin 'px;}\n '
179             
'.keyboardrow2 {margin-left: ' + (margin 20) + 'px;}\n '
180             
'.keyboardrow3 {margin-left: ' + (margin 40) + 'px;}\n '
181             
'.keyboard .key {float: left; width: 28px; height: 30px; border: 1px solid; margin: 2px; padding:
 3px; font-weight: bold;}\n '
182             
'.keyboard .key div {float: right; font-weight: normal;}\n';
183         var 
css document.createElement('style');
184         
css.setAttribute('type''text/css');
185         if (
typeof css.styleSheet == 'undefined') {
186             
css.appendChild(document.createTextNode(i18n.css));
187         } else {
188             
css.styleSheet.cssText i18n.css;
189         }
190         
document.getElementsByTagName('head')[0].appendChild(css);
191     }
192     return 
keyboard;
193 }
194
195  
/**
196  * Internal array of existing keyboard displays
197  * @var array
198  */
199 /* protected */ 
i18n.keyboards = []
200
201
/**
202  * Toggles the display of a keyboard
203  * @param str id
204  */
205 /* public */ 
i18n.toggleKeyboard = function(id) {
206     var 
keyboard document.getElementById(id);
207     if (!
keyboard) {
208         return;
209     }
210     
i18n.keyboards[i18n.keyboards.length] = id;
211     var 
link document.getElementById('keyboardlink_' id);
212     if (
keyboard.innerHTML == '' && i18n.languageName != 'english') {
213         
keyboard.innerHTML i18n.getKeyboardLayout();
214         
link.style.border='1px inset';
215     } else {
216         
keyboard.innerHTML '';
217         
link.style.border='0px';
218     }
219 }
220
221
/**
222  * Changes the keyboard layout to the currently selected language
223  */
224 /* protected */ 
i18n.updateKeyboard = function() {
225     var 
keyboardLayout i18n.getKeyboardLayout();
226     var 
keyboard;
227     for (var 
i in i18n.keyboards) {
228         
keyboard document.getElementById(i18n.keyboards[i]);
229         if (
keyboard.innerHTML != '') {
230             
keyboard.innerHTML keyboardLayout;
231         }
232     }
233 }
234
235
/**
236  * Change the current language
237  * @param str lang
238  */
239 /* public */ 
i18n.setLanguage = function(lang) {
240     var 
prevButton; var currentButton;
241     for (var 
1<= i18n.languageLinkCountx++) {
242         
prevButton document.getElementById('languagelink_' i18n.languageName '_' x);
243         
currentButton document.getElementById('languagelink_' lang '_' x);
244         if (
prevButton) {
245             
prevButton.style.border='0px';
246         }
247         if (
currentButton) {
248             
currentButton.style.border='1px inset';
249         }
250     }
251     
i18n.language = (typeof i18n.languages[lang] != 'undefined' i18n.languages[lang] : 'english');
252     
i18n.languageName lang
253     i18n
.updateKeyboard();
254 }
255
256
/**
257  * Limits the array of languages available (default is all languages) and if to include the default language
 
(English.)
258  * 
FYISetting to just a single language and hiding English will restrict form entry to that language.
259  * @
param mixed langs Can be a string or an array containing multiple strings
260  
* @param Boolean hideEnglish
261  
*/
262
/* public */ i18n.setLanguages = function(langshideEnglish) {
263     if (
typeof i18n.initialized == 'undefined') {
264         
i18n();
265     }
266     
i18n.hideEnglish = (typeof hideEnglish == 'undefined' false hideEnglish);
267     if (
typeof langs != 'undefined') {
268         
i18n.langs = (typeof langs == 'object' langs : [langs]);
269     } else {
270         
i18n.langs = [];
271         var 
0;
272         for (var 
key in i18n.languages) {
273             
i18n.langs[x++] = key;
274         }
275     }
276     if (
i18n.hideEnglish) {
277         
i18n.setLanguage(i18n.langs[0]);
278     }
279 }
280
281  
/**
282  * Internal counter of language-link button-arrays that are displayed
283  * @var int
284  */
285 /* private */ 
i18n.languageLinkCount 0;
286
287
/**
288  * Gets a link buttoms to change languages - buttons are returned in the order the languages are defined in
 
i18n.setLanguages()
289  * @return 
str
290  
*/
291
/* public */ i18n.getLanguageLinks = function() {
292     
i18n.languageLinkCount++;
293     var 
selected ' style="border: 1px inset;"';
294     var 
languageLinks '';
295     if (!
i18n.hideEnglish) {
296         
languageLinks += '<a href="javascript: i18n.setLanguage(\'english\'); void(0);" title="English"
 id="languagelink_english_' 
i18n.languageLinkCount '"';
297         if (
i18n.languageName == 'english') {
298             
languageLinks += selected;
299         }
300         
languageLinks += '>EN</a>';
301     }
302     if (
typeof i18n.langs != 'undefined' && (i18n.langs.length == && languageLinks == '') || i18n.langs.length
 
== 0) { //no buttons if only one language
303         
return '';
304     }
305     for (var 
i in i18n.langs) {
306         if (
typeof i18n.languages[i18n.langs[i]] != 'undefined') {
307             
languageLinks += ' ' '<a href="javascript: i18n.setLanguage(\'' i18n.langs[i] + '\'); void(0);"
 title="Phonetic ' 
i18n.langs[i].substring(01).toUpperCase() + i18n.langs[i].substring(1) + '"
 id="languagelink_' 
i18n.langs[i] + '_' i18n.languageLinkCount '"';
308             if (
i18n.languageName == i18n.langs[i]) {
309                 
languageLinks += selected;
310             }
311             
languageLinks += '>' i18n.langs[i].substring(02).toUpperCase() + '</a>';
312         }
313     }
314     return 
languageLinks;
315 }
316
317
/**
318  * Gets a link to toggle keyboard display
319  * @param str id Determines which keyboard to open (created by i18n.getKeyboard)
320  * @param str label Optional, the word "keyboard" will be used if omitted
321  * @return str
322  */
323 /* protected */ 
i18n.getKeyboardLink = function(idlabel) {
324     if (
typeof label == 'undefined') {
325         
label 'keyboard';
326     }
327     return 
'<a href="javascript: i18n.toggleKeyboard(\'' id '\'); void(0);" id="keyboardlink_' id '">' +
 
label '</a>';
328 }
329
330
/**
331  * Gets a keyboard link to display the language key-mapping
332  * @param str id Optional, keyboard will replace the contents of the element for the ID supplied; if id is omitted
 
then keyboard will display inline
333  
* @param str label Optionalthe word "keyboard" will be used if omitted
334  
* @return str
335  
*/
336
/* public */ i18n.getKeyboard = function(idlabel) {
337     if (
typeof id == 'undefined') {
338         
id 'keyboard_' Math.floor(Math.random() * 1000);
339         return 
i18n.getKeyboardLink(idlabel) + '<div id="' id '"></div>';
340     } else {
341         return 
i18n.getKeyboardLink(idlabel);
342     }
343 }