tr8n 3.2.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Gemfile.lock +3 -1
  2. data/app/assets/javascripts/tr8n/tr8n-compiled.js +336 -0
  3. data/app/assets/stylesheets/tr8n/admin.css.scss +23 -0
  4. data/app/assets/stylesheets/tr8n/components.css.scss +23 -0
  5. data/app/assets/stylesheets/tr8n/keyboard_1_49.css +271 -0
  6. data/app/assets/stylesheets/tr8n/layout.css.scss +23 -0
  7. data/app/assets/stylesheets/tr8n/tr8n.css.scss +1 -1
  8. data/app/controllers/tr8n/api/v1/base_controller.rb +6 -0
  9. data/app/controllers/tr8n/api/v1/language_controller.rb +7 -10
  10. data/app/controllers/tr8n/api/v1/translation_controller.rb +0 -1
  11. data/app/javascript/compile.rb +37 -0
  12. data/app/javascript/compile.sh +1 -0
  13. data/app/javascript/compressors/google/COPYING +202 -0
  14. data/app/javascript/compressors/google/README +292 -0
  15. data/app/javascript/compressors/google/compiler.jar +0 -0
  16. data/app/javascript/config.yml +66 -0
  17. data/app/javascript/src/base.js +35 -0
  18. data/app/javascript/src/effects.js +67 -0
  19. data/app/javascript/src/ext/inflector.js +309 -0
  20. data/app/{assets/javascripts/tr8n → javascript/src/ext}/jsDraw2D.js +0 -0
  21. data/app/{assets/javascripts/tr8n → javascript/src/ext}/keyboard_1_36.js +0 -0
  22. data/app/{assets/javascripts/tr8n → javascript/src/ext}/keyboard_1_44.js +0 -0
  23. data/app/javascript/src/ext/keyboard_1_49.js +1796 -0
  24. data/app/javascript/src/ext/md5.js +209 -0
  25. data/app/{assets/javascripts/tr8n → javascript/src/ext}/shortcut.js +0 -0
  26. data/app/javascript/src/init.js +47 -0
  27. data/app/javascript/src/language.js +38 -0
  28. data/app/javascript/src/logger.js +203 -0
  29. data/app/{assets/javascripts/tr8n/tr8n_prototype_effects.js → javascript/src/prototype/effects.js} +5 -5
  30. data/app/javascript/src/proxy.js +254 -0
  31. data/app/javascript/src/rules/date_rule.js +37 -0
  32. data/app/javascript/src/rules/gender_list_rule.js +37 -0
  33. data/app/javascript/src/rules/gender_rule.js +87 -0
  34. data/app/javascript/src/rules/language_rule.js +55 -0
  35. data/app/javascript/src/rules/list_rule.js +37 -0
  36. data/app/javascript/src/rules/numeric_rule.js +95 -0
  37. data/app/javascript/src/tml/label.js +60 -0
  38. data/app/javascript/src/tml/token.js +107 -0
  39. data/app/javascript/src/tokens/data_token.js +45 -0
  40. data/app/javascript/src/tokens/decoration_token.js +82 -0
  41. data/app/javascript/src/tokens/token.js +121 -0
  42. data/app/javascript/src/tokens/transform_token.js +106 -0
  43. data/app/javascript/src/translation_key.js +183 -0
  44. data/app/javascript/src/ui/language_case_manager.js +155 -0
  45. data/app/javascript/src/ui/language_selector.js +126 -0
  46. data/app/javascript/src/ui/lightbox.js +72 -0
  47. data/app/javascript/src/ui/translator.js +257 -0
  48. data/app/javascript/src/utils.js +286 -0
  49. data/app/models/tr8n/language_case.rb +27 -16
  50. data/app/models/tr8n/language_case_rule.rb +24 -7
  51. data/app/models/tr8n/translation_key.rb +23 -21
  52. data/app/views/tr8n/common/_scripts.html.erb +8 -10
  53. data/app/views/tr8n/language_cases/_manager_header.html.erb +3 -3
  54. data/app/views/tr8n/language_cases/manager.html.erb +2 -2
  55. data/app/views/tr8n/translations/_original_phrase.html.erb +1 -1
  56. data/lib/tr8n/extensions/action_view_extension.rb +8 -1
  57. data/lib/tr8n/keyboard_mapping.rb +101 -0
  58. data/lib/tr8n/token.rb +1 -2
  59. data/lib/tr8n/version.rb +1 -1
  60. data/spec/models/tr8n/gender_rule_spec.rb +6 -6
  61. data/spec/models/tr8n/language_case_rule_spec.rb +219 -1
  62. data/spec/models/tr8n/language_case_spec.rb +51 -1
  63. data/spec/models/tr8n/translation_key_spec.rb +256 -0
  64. data/tr8n.gemspec +2 -1
  65. metadata +129 -47
  66. data/app/assets/javascripts/tr8n/tr8n.js +0 -905
  67. data/app/assets/javascripts/tr8n/tr8n_client_sdk.js +0 -1472
@@ -0,0 +1,72 @@
1
+ /****************************************************************************
2
+ Copyright (c) 2010-2012 Michael Berkovich, Ian McDaniel, tr8n.net
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ ****************************************************************************/
23
+
24
+ Tr8n.Lightbox = function() {
25
+ this.container = document.createElement('div');
26
+ this.container.className = 'tr8n_lightbox';
27
+ this.container.id = 'tr8n_lightbox';
28
+ this.container.style.display = "none";
29
+
30
+ this.overlay = document.createElement('div');
31
+ this.overlay.className = 'tr8n_lightbox_overlay';
32
+ this.overlay.id = 'tr8n_lightbox_overlay';
33
+ this.overlay.style.display = "none";
34
+
35
+ document.body.appendChild(this.container);
36
+ document.body.appendChild(this.overlay);
37
+ }
38
+
39
+ Tr8n.Lightbox.prototype = {
40
+
41
+ hide: function() {
42
+ this.container.style.display = "none";
43
+ this.overlay.style.display = "none";
44
+ Tr8n.Utils.showFlash();
45
+ },
46
+
47
+ show: function(url, opts) {
48
+ var self = this;
49
+ opts = opts || {};
50
+ if(tr8nTranslator) tr8nTranslator.hide();
51
+ if(tr8nLanguageSelector) tr8nLanguageSelector.hide();
52
+ if(tr8nLanguageCaseManager) tr8nLanguageCaseManager.hide();
53
+ Tr8n.Utils.hideFlash();
54
+
55
+ this.container.innerHTML = "<div class='inner'><div class='bd'><img src='/assets/tr8n/spinner.gif' style='vertical-align:middle'> Loading...</div></div>";
56
+
57
+ this.overlay.style.display = "block";
58
+
59
+ opts["width"] = opts["width"] || 700;
60
+ opts["height"] = opts["height"] || 520;
61
+
62
+ this.container.style.width = opts["width"] + 'px';
63
+ this.container.style.height = opts["height"] + 'px';
64
+ this.container.style.marginLeft = -opts["width"]/2 + 'px';
65
+ this.container.style.marginTop = -opts["height"]/2 + 'px';
66
+ this.container.style.display = "block";
67
+
68
+ Tr8n.Utils.update('tr8n_lightbox', url, {
69
+ evalScripts: true
70
+ });
71
+ }
72
+ }
@@ -0,0 +1,257 @@
1
+ /****************************************************************************
2
+ Copyright (c) 2010-2012 Michael Berkovich, Ian McDaniel, tr8n.net
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ ****************************************************************************/
23
+
24
+ Tr8n.Translator = function(options) {
25
+ var self = this;
26
+ this.options = options;
27
+ this.translation_key_id = null;
28
+ this.suggestion_tokens = null;
29
+
30
+ this.container = document.createElement('div');
31
+ this.container.className = 'tr8n_translator';
32
+ this.container.id = 'tr8n_translator';
33
+ this.container.style.display = "none";
34
+
35
+ document.body.appendChild(this.container);
36
+
37
+
38
+ var event_type = Tr8n.Utils.isOpera() ? 'click' : 'contextmenu';
39
+
40
+ Tr8n.Utils.addEvent(document, event_type, function(e) {
41
+ if (Tr8n.Utils.isOpera() && !e.ctrlKey) return;
42
+
43
+ var translatable_node = Tr8n.Utils.findElement(e, ".tr8n_translatable");
44
+ var link_node = Tr8n.Utils.findElement(e, "a");
45
+
46
+ if (translatable_node == null) return;
47
+
48
+ if (link_node) {
49
+ var temp_href = link_node.href;
50
+ link_node.href='javascript:void(0);';
51
+ setTimeout(function() {link_node.href = temp_href;}, 500);
52
+ }
53
+
54
+ if (e.stop) e.stop();
55
+ if (e.preventDefault) e.preventDefault();
56
+ if (e.stopPropagation) e.stopPropagation();
57
+
58
+ self.show(translatable_node);
59
+ return false;
60
+ });
61
+ }
62
+
63
+ Tr8n.Translator.prototype = {
64
+ hide: function() {
65
+ this.container.style.display = "none";
66
+ Tr8n.Utils.showFlash();
67
+ },
68
+
69
+ show: function(translatable_node) {
70
+ var self = this;
71
+ if (tr8nLanguageSelector) tr8nLanguageSelector.hide();
72
+ if (tr8nLightbox) tr8nLightbox.hide();
73
+ if (tr8nLanguageCaseManager) tr8nLanguageCaseManager.hide();
74
+ Tr8n.Utils.hideFlash();
75
+
76
+ var html = "";
77
+ var splash_screen = Tr8n.element('tr8n_splash_screen');
78
+
79
+ if (splash_screen) {
80
+ html += splash_screen.innerHTML;
81
+ } else {
82
+ html += "<div style='font-size:18px;text-align:center; margin:5px; padding:10px; background-color:black;'>";
83
+ html += " <img src='/assets/tr8n/tr8n_logo.jpg' style='width:280px; vertical-align:middle;'>";
84
+ html += " <img src='/assets/tr8n/loading3.gif' style='width:200px; height:20px; vertical-align:middle;'>";
85
+ html += "</div>"
86
+ }
87
+ this.container.innerHTML = html;
88
+ this.container.style.display = "block";
89
+
90
+ var stem = {v:"top", h:"left",width:10, height:12};
91
+ var stem_type = "top_left";
92
+ var target_dimensions = {width:translatable_node.offsetWidth, height:translatable_node.offsetHeight};
93
+ var target_position = Tr8n.Utils.cumulativeOffset(translatable_node);
94
+ var container_position = {
95
+ left: (target_position[0] + 'px'),
96
+ top : (target_position[1] + target_dimensions.height + stem.height + 'px')
97
+ }
98
+
99
+ var stem_offset = target_dimensions.width/2;
100
+ var scroll_buffer = 100;
101
+ var scroll_height = target_position[1] - scroll_buffer;
102
+
103
+ if (window.innerWidth < target_position[0] + target_dimensions.width + window.innerWidth/2) {
104
+ container_position.left = target_position[0] + target_dimensions.width - this.container.offsetWidth + "px";
105
+ stem_offset = target_dimensions.width/2;
106
+ stem.h = "right";
107
+ }
108
+
109
+ window.scrollTo(target_position[0], scroll_height);
110
+ this.container.style.left = container_position.left;
111
+ this.container.style.top = container_position.top;
112
+ this.translation_key_id = translatable_node.getAttribute('translation_key_id');
113
+
114
+ window.setTimeout(function() {
115
+ Tr8n.Utils.update('tr8n_translator', '/tr8n/language/translator', {
116
+ evalScripts: true,
117
+ parameters: {
118
+ translation_key_id: self.translation_key_id,
119
+ stem_type: stem.v + "_" + stem.h,
120
+ stem_offset: stem_offset
121
+ }
122
+ });
123
+ }, 500);
124
+ },
125
+
126
+ reportTranslation: function(key, translation_id) {
127
+ var msg = "Reporting this translation will remove it from this list and the translator will be put on a watch list. \n\nAre you sure you want to report this translation?";
128
+ if (!confirm(msg)) return;
129
+ this.voteOnTranslation(key, translation_id, -1000);
130
+ },
131
+
132
+ voteOnTranslation: function(key, translation_id, vote) {
133
+ Tr8n.Effects.hide('tr8n_votes_for_' + translation_id);
134
+ Tr8n.Effects.show('tr8n_spinner_for_' + translation_id);
135
+
136
+ // the long version updates and reorders translations - used in translator and phrase list
137
+ // the short version only updates the total results - used everywhere else
138
+ if (Tr8n.element('tr8n_translator_votes_for_' + key)) {
139
+ Tr8n.Utils.update('tr8n_translator_votes_for_' + key, '/tr8n/translations/vote', {
140
+ parameters: {
141
+ translation_id: translation_id,
142
+ vote: vote
143
+ },
144
+ method: 'post'
145
+ });
146
+ } else {
147
+ Tr8n.Utils.update('tr8n_votes_for_' + translation_id, '/tr8n/translations/vote', {
148
+ parameters: {
149
+ translation_id: translation_id,
150
+ vote: vote,
151
+ short_version: true
152
+ },
153
+ method: 'post',
154
+ onComplete: function() {
155
+ Tr8n.Effects.hide('tr8n_spinner_for_' + translation_id);
156
+ Tr8n.Effects.show('tr8n_votes_for_' + translation_id);
157
+ }
158
+ });
159
+ }
160
+ },
161
+
162
+ insertDecorationToken: function (token, txtarea_id) {
163
+ txtarea_id = txtarea_id || 'tr8n_translator_translation_label';
164
+ Tr8n.Utils.wrapText(txtarea_id, "[" + token + ": ", "]");
165
+ },
166
+
167
+ insertToken: function (token, txtarea_id) {
168
+ txtarea_id = txtarea_id || 'tr8n_translator_translation_label';
169
+ Tr8n.Utils.insertAtCaret(txtarea_id, "{" + token + "}");
170
+ },
171
+
172
+ switchTranslatorMode: function(translation_key_id, mode, source_url) {
173
+ Tr8n.Utils.update('tr8n_translator_container', '/tr8n/language/translator', {
174
+ parameters: {translation_key_id: translation_key_id, mode: mode, source_url: source_url},
175
+ evalScripts: true
176
+ });
177
+ },
178
+
179
+ submitTranslation: function() {
180
+ Tr8n.Effects.hide('tr8n_translator_translation_container');
181
+ Tr8n.Effects.hide('tr8n_translator_buttons_container');
182
+ Tr8n.Effects.show('tr8n_translator_spinner');
183
+ Tr8n.Effects.submit('tr8n_translator_form');
184
+ },
185
+
186
+ submitViewingUserDependency: function() {
187
+ Tr8n.element('tr8n_translator_translation_has_dependencies').value = "true";
188
+ this.submitTranslation();
189
+ },
190
+
191
+ submitDependencies: function() {
192
+ Tr8n.Effects.hide('tr8n_translator_buttons_container');
193
+ Tr8n.Effects.hide('tr8n_translator_dependencies_container');
194
+ Tr8n.Effects.show('tr8n_translator_spinner');
195
+ Tr8n.element('tr8n_translator_form').action = '/tr8n/translations/permutate';
196
+ Tr8n.Effects.submit('tr8n_translator_form');
197
+ },
198
+
199
+ translate: function(label, callback, opts) {
200
+ opts = opts || {}
201
+ Tr8n.Utils.ajax('/tr8n/language/translate', {
202
+ method: 'post',
203
+ parameters: {
204
+ label: label,
205
+ description: opts.description,
206
+ tokens: opts.tokens,
207
+ options: opts.options,
208
+ language: opts.language
209
+ },
210
+ onSuccess: function(r) {
211
+ if(callback) callback(r.responseText);
212
+ }
213
+ });
214
+ },
215
+
216
+ translateBatch: function(phrases, callback) {
217
+ Tr8n.Utils.ajax('/tr8n/language/translate', {
218
+ method: 'post',
219
+ parameters: {phrases: phrases},
220
+ onSuccess: function(r) {
221
+ if (callback) callback(r.responseText);
222
+ }
223
+ });
224
+ },
225
+
226
+ processSuggestedTranslation: function(response) {
227
+ if (response == null ||response.data == null || response.data.translations==null || response.data.translations.length == 0)
228
+ return;
229
+ var suggestion = response.data.translations[0].translatedText;
230
+ if (this.suggestion_tokens) {
231
+ var tokens = this.suggestion_tokens.split(",");
232
+ this.suggestion_tokens = null;
233
+ for (var i=0; i<tokens.length; i++) {
234
+ suggestion = Tr8n.Utils.replaceAll(suggestion, "(" + i + ")", tokens[i]);
235
+ }
236
+ }
237
+ Tr8n.element("tr8n_translation_suggestion_" + this.translation_key_id).innerHTML = suggestion;
238
+ Tr8n.element("tr8n_google_suggestion_container_" + this.translation_key_id).style.display = "block";
239
+ var suggestion_section = Tr8n.element('tr8n_google_suggestion_section');
240
+ if (suggestion_section) suggestion_section.style.display = "block";
241
+ },
242
+
243
+ suggestTranslation: function(translation_key_id, original, tokens, from_lang, to_lang) {
244
+ if (Tr8n.google_api_key == null) return;
245
+
246
+ this.suggestion_tokens = tokens;
247
+ this.translation_key_id = translation_key_id;
248
+ var new_script = document.createElement('script');
249
+ new_script.type = 'text/javascript';
250
+ var source_text = escape(original);
251
+ var api_source = 'https://www.googleapis.com/language/translate/v2?key=' + Tr8n.google_api_key;
252
+ var source = api_source + '&source=' + from_lang + '&target=' + to_lang + '&callback=tr8nTranslator.processSuggestedTranslation&q=' + source_text;
253
+ new_script.src = source;
254
+ document.getElementsByTagName('head')[0].appendChild(new_script);
255
+ }
256
+
257
+ }
@@ -0,0 +1,286 @@
1
+ /****************************************************************************
2
+ Copyright (c) 2010-2012 Michael Berkovich, Ian McDaniel, tr8n.net
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ ****************************************************************************/
23
+
24
+ Tr8n.Utils = {
25
+
26
+ hideFlash: function() {
27
+ // alert("Hiding");
28
+ var embeds = document.getElementsByTagName('embed');
29
+ for(i = 0; i < embeds.length; i++) {
30
+ embeds[i].style.visibility = 'hidden';
31
+ }
32
+ },
33
+
34
+ showFlash: function() {
35
+ // alert("Showing");
36
+ var embeds = document.getElementsByTagName('embed');
37
+ for(i = 0; i < embeds.length; i++) {
38
+ embeds[i].style.visibility = 'visible';
39
+ }
40
+ },
41
+
42
+ isOpera: function() {
43
+     return /Opera/.test(navigator.userAgent);
44
+   },
45
+
46
+ addEvent: function(elm, evType, fn, useCapture) {
47
+ useCapture = useCapture || false;
48
+ if (elm.addEventListener) {
49
+ elm.addEventListener(evType, fn, useCapture);
50
+ return true;
51
+ } else if (elm.attachEvent) {
52
+ var r = elm.attachEvent('on' + evType, fn);
53
+ return r;
54
+ } else {
55
+ elm['on' + evType] = fn;
56
+ }
57
+ },
58
+
59
+ toQueryParams: function (obj) {
60
+ if (typeof obj == 'undefined' || obj == null) return "";
61
+ if (typeof obj == 'string') return obj;
62
+
63
+ var qs = [];
64
+ for(p in obj) {
65
+ qs.push(p + "=" + encodeURIComponent(obj[p]))
66
+ }
67
+ return qs.join("&")
68
+ },
69
+
70
+ serializeForm: function(form) {
71
+ var els = Tr8n.element(form).elements;
72
+ var form_obj = {}
73
+ for(i=0; i < els.length; i++) {
74
+ if (els[i].type == 'checkbox' && !els[i].checked) continue;
75
+ form_obj[els[i].name] = els[i].value;
76
+ }
77
+ return form_obj;
78
+ },
79
+
80
+ indexOf: function(array, item, i) {
81
+ i || (i = 0);
82
+ var length = array.length;
83
+ if (i < 0) i = length + i;
84
+ for (; i < length; i++)
85
+ if (array[i] === item) return i;
86
+ return -1;
87
+ },
88
+
89
+ replaceAll: function(label, key, value) {
90
+ while (label.indexOf(key) != -1) {
91
+ label = label.replace(key, value);
92
+ }
93
+ return label;
94
+ },
95
+
96
+ trim: function(string) {
97
+ return string.replace(/^\s+|\s+$/g,"");
98
+ },
99
+
100
+ ltrim: function(string) {
101
+ return string.replace(/^\s+/,"");
102
+ },
103
+
104
+ rtrim: function(string) {
105
+ return string.replace(/\s+$/,"");
106
+ },
107
+
108
+ getRequest: function() {
109
+ var factories = [
110
+ function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
111
+ function() { return new XMLHttpRequest(); },
112
+ function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
113
+ ];
114
+ for(var i = 0; i < factories.length; i++) {
115
+ try {
116
+ var request = factories[i]();
117
+ if (request != null) return request;
118
+ } catch(e) {continue;}
119
+ }
120
+ },
121
+
122
+ ajax: function(url, options) {
123
+ options = options || {};
124
+ options.parameters = Tr8n.Utils.toQueryParams(options.parameters);
125
+ options.method = options.method || 'get';
126
+
127
+ var self=this;
128
+ if (options.method == 'get' && options.parameters != '') {
129
+ url = url + (url.indexOf('?') == -1 ? '?' : '&') + options.parameters;
130
+ }
131
+
132
+ var request = this.getRequest();
133
+
134
+ request.onreadystatechange = function() {
135
+ if(request.readyState == 4) {
136
+ if (request.status == 200) {
137
+ if(options.onSuccess) options.onSuccess(request);
138
+ if(options.onComplete) options.onComplete(request);
139
+ if(options.evalScripts) self.evalScripts(request.responseText);
140
+ } else {
141
+ if(options.onFailure) options.onFailure(request)
142
+ if(options.onComplete) options.onComplete(request)
143
+ }
144
+ }
145
+ }
146
+
147
+ request.open(options.method, url, true);
148
+ request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
149
+ request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
150
+ request.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
151
+ request.send(options.parameters);
152
+ },
153
+
154
+ update: function(element_id, url, options) {
155
+ options.onSuccess = function(response) {
156
+ Tr8n.element(element_id).innerHTML = response.responseText;
157
+ };
158
+ Tr8n.Utils.ajax(url, options);
159
+ },
160
+
161
+ evalScripts: function(html){
162
+ var script_re = '<script[^>]*>([\\S\\s]*?)<\/script>';
163
+ var matchAll = new RegExp(script_re, 'img');
164
+ var matchOne = new RegExp(script_re, 'im');
165
+ var matches = html.match(matchAll) || [];
166
+ for(var i=0,l=matches.length;i<l;i++){
167
+ var script = (matches[i].match(matchOne) || ['', ''])[1];
168
+ // console.info(script)
169
+ // alert(script);
170
+ eval(script);
171
+ }
172
+ },
173
+
174
+ hasClassName:function(el, cls){
175
+ var exp = new RegExp("(^|\\s)"+cls+"($|\\s)");
176
+ return (el.className && exp.test(el.className))?true:false;
177
+ },
178
+
179
+ findElement: function (e,selector,el) {
180
+ var event = e || window.event;
181
+ var target = el || event.target || event.srcElement;
182
+ if(target == document.body) return null;
183
+ var condition = (selector.match(/^\./)) ? this.hasClassName(target,selector.replace(/^\./,'')) : (target.tagName.toLowerCase() == selector.toLowerCase());
184
+ if(condition) {
185
+ return target;
186
+ } else {
187
+ return this.findElement(e,selector,target.parentNode);
188
+ }
189
+ },
190
+
191
+ cumulativeOffset: function(element) {
192
+ var valueT = 0, valueL = 0;
193
+ do {
194
+ valueT += element.offsetTop || 0;
195
+ valueL += element.offsetLeft || 0;
196
+ element = element.offsetParent;
197
+ } while (element);
198
+ return [valueL, valueT];
199
+ },
200
+
201
+ wrapText: function (obj_id, beginTag, endTag) {
202
+ var obj = document.getElementById(obj_id);
203
+
204
+ if (typeof obj.selectionStart == 'number') {
205
+ // Mozilla, Opera, and other browsers
206
+ var start = obj.selectionStart;
207
+ var end = obj.selectionEnd;
208
+ obj.value = obj.value.substring(0, start) + beginTag + obj.value.substring(start, end) + endTag + obj.value.substring(end, obj.value.length);
209
+
210
+ } else if(document.selection) {
211
+ // Internet Explorer
212
+ obj.focus();
213
+ var range = document.selection.createRange();
214
+ if(range.parentElement() != obj)
215
+ return false;
216
+
217
+ if(typeof range.text == 'string')
218
+ document.selection.createRange().text = beginTag + range.text + endTag;
219
+ } else
220
+ obj.value += beginTag + " " + endTag;
221
+
222
+ return true;
223
+ },
224
+
225
+ insertAtCaret: function (areaId, text) {
226
+ var txtarea = document.getElementById(areaId);
227
+ var scrollPos = txtarea.scrollTop;
228
+ var strPos = 0;
229
+ var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false ) );
230
+
231
+ if (br == "ie") {
232
+ txtarea.focus();
233
+ var range = document.selection.createRange();
234
+ range.moveStart ('character', -txtarea.value.length);
235
+ strPos = range.text.length;
236
+ } else if (br == "ff")
237
+ strPos = txtarea.selectionStart;
238
+
239
+ var front = (txtarea.value).substring(0, strPos);
240
+ var back = (txtarea.value).substring(strPos, txtarea.value.length);
241
+ txtarea.value=front+text+back;
242
+
243
+ strPos = strPos + text.length;
244
+ if (br == "ie") {
245
+ txtarea.focus();
246
+ var range = document.selection.createRange();
247
+ range.moveStart ('character', -txtarea.value.length);
248
+ range.moveStart ('character', strPos);
249
+ range.moveEnd ('character', 0); range.select();
250
+ } else if (br == "ff") {
251
+ txtarea.selectionStart = strPos;
252
+ txtarea.selectionEnd = strPos;
253
+ txtarea.focus();
254
+ }
255
+ txtarea.scrollTop = scrollPos;
256
+ },
257
+
258
+ toggleKeyboards: function() {
259
+ if(!VKI_attach) return;
260
+ if (!this.keyboardMode) {
261
+ this.keyboardMode = true;
262
+
263
+ var elements = document.getElementsByTagName("input");
264
+ for(i=0; i<elements.length; i++) {
265
+ if (elements[i].type == "text") VKI_attach(elements[i]);
266
+ }
267
+ elements = document.getElementsByTagName("textarea");
268
+ for(i=0; i<elements.length; i++) {
269
+ VKI_attach(elements[i]);
270
+ }
271
+ } else {
272
+ window.location.reload();
273
+ }
274
+ },
275
+
276
+ displayShortcuts: function() {
277
+ if (tr8nLightbox)
278
+ tr8nLightbox.show('/tr8n/help/lb_shortcuts', {width:400, height:480});
279
+ },
280
+
281
+ displayStatistics: function() {
282
+ if (tr8nLightbox)
283
+ tr8nLightbox.show('/tr8n/help/lb_stats', {width:420, height:400});
284
+ }
285
+
286
+ }