BidiUtils.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| BI and PM: prmt
  5. *| (C) Copyright IBM Corp. 2002, 2011
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. /**
  13. * This file provides methods setting text direction for various HTML control
  14. * (dynamic input fields, static labels ...)
  15. *
  16. */
  17. var PRMT_BidiUtils =
  18. {
  19. // Bidi constants
  20. BIDI_TXTDIR_CONTEXTUAL : "auto",
  21. BIDI_TXTDIR_RTL : "rtl",
  22. BIDI_TXTDIR_LTR : "ltr",
  23. BIDI_CHAR_LRE : "\u202A",
  24. BIDI_CHAR_RLE : "\u202B",
  25. BIDI_CHAR_PDF : "\u202C",
  26. BIDI_CHAR_LRM : "\u200E",
  27. BIDI_CHAR_RLM : "\u200F",
  28. VK_SHIFT : 0x10,
  29. VK_END : 0x23,
  30. VK_HOME : 0x24,
  31. VK_LEFT : 0x25,
  32. VK_RIGHT : 0x27,
  33. /**
  34. * It fixes the direction (using the CSS style direction) of the INPUT element depending on the setting and the
  35. * input value. If input.value is a right to left language (like Arabic, Hebrew), then change the input style to right to left.
  36. * txtAlignPref is for future use in case the user prefers a fixed alignnment (not depending on text direction)
  37. */
  38. fixInputDirection : function(inputElement, txtDir, txtAlignPref){
  39. if (inputElement !== null && (inputElement.tagName == 'INPUT' || inputElement.tagName == 'TEXTAREA')) {
  40. inputElement.style.direction = PRMT_BidiUtils.getTextDirection(inputElement.value, txtDir);
  41. }
  42. },
  43. /**
  44. * This function enforces the text direction of a given string by adding LRE/RLE PDF header and footer
  45. */
  46. enforceBidiDirection : function(stringValue, txtDir){
  47. var finalDir = PRMT_BidiUtils.getTextDirection(stringValue, txtDir);
  48. var finalValue = stringValue;
  49. if (finalDir == "ltr") {
  50. finalValue = PRMT_BidiUtils.BIDI_CHAR_LRE + finalValue + PRMT_BidiUtils.BIDI_CHAR_PDF;
  51. } else if (finalDir == "rtl") {
  52. finalValue = PRMT_BidiUtils.BIDI_CHAR_RLE + finalValue + PRMT_BidiUtils.BIDI_CHAR_PDF;
  53. }
  54. return finalValue;
  55. },
  56. /**
  57. * Returns the text direction of a given string depending on the setting and the string text
  58. */
  59. getTextDirection : function(val, txtDir){
  60. var finalDir = txtDir;
  61. if (txtDir == PRMT_BidiUtils.BIDI_TXTDIR_CONTEXTUAL){
  62. finalDir =((PRMT_BidiUtils.isRTLString(val))? PRMT_BidiUtils.BIDI_TXTDIR_RTL : PRMT_BidiUtils.BIDI_TXTDIR_LTR);
  63. }
  64. return finalDir;
  65. },
  66. /**
  67. * Detect the direction (RTL || LTR ) of a string
  68. * The first strong character of the string determines the direction of the string
  69. *
  70. */
  71. isRTLString : function(stringValue){
  72. var result = false;
  73. for (var i = 0; i < stringValue.length; i++) {
  74. if (PRMT_BidiUtils.isRTLChar(stringValue.charCodeAt(i))) {
  75. result = true;
  76. break
  77. }
  78. else if(PRMT_BidiUtils.isLatinChar(stringValue.charCodeAt(i))) {
  79. break;
  80. }
  81. }
  82. return result;
  83. },
  84. /**
  85. * Determines if the passed character c is a RTL (Hebrew or Arabic) char
  86. */
  87. isRTLChar : function(c){
  88. var result = false;
  89. if ((c >= 0x05d0 && c <= 0x05ff) ||
  90. (c >= 0x0600 && c <= 0x065f) ||
  91. (c >= 0x066a && c <= 0x06ef) ||
  92. (c >= 0x06fa && c <= 0x07ff) ||
  93. (c >= 0xfb1d && c <= 0xfdff) ||
  94. (c >= 0xfe70 && c <= 0xfefc)) {
  95. result = true;
  96. }
  97. return result;
  98. },
  99. /**
  100. * Determines if the passed character c is a Latin char
  101. */
  102. isLatinChar : function(c){
  103. return (((c > 64 && c < 91)||(c > 96 && c < 123))? true : false);
  104. },
  105. /**
  106. * Search for the first ancestor element(including the element itself) to have a defined direction
  107. */
  108. lookupDirection : function(elem){
  109. var lookupDir = null;
  110. while ( (lookupDir != PRMT_BidiUtils.BIDI_TXTDIR_LTR) && (lookupDir != PRMT_BidiUtils.BIDI_TXTDIR_RTL) && elem && elem.parentNode ) {
  111. elem = elem.parentNode;
  112. lookupDir = ( (elem.style && elem.style.direction) ? elem.style.direction : elem.dir);
  113. }
  114. return lookupDir;
  115. },
  116. /**
  117. * Determines if a string contains a RTL char
  118. */
  119. containsRTLChar : function(stringValue){
  120. var result = false;
  121. for (var i = 0; i < stringValue.length; i++) {
  122. if (PRMT_BidiUtils.isRTLChar(stringValue.charCodeAt(i))) {
  123. result = true;
  124. break
  125. }
  126. }
  127. return result;
  128. },
  129. /**
  130. * This function determines if there is a RTL char between the index i and previous in the buffer
  131. */
  132. isCharBeforeRTLChar : function(buffer, i, previous) {
  133. var result = false;
  134. var prevChar;
  135. while (i > 0 && i != previous) {
  136. prevChar = buffer.charCodeAt(i-1);
  137. if(PRMT_BidiUtils.isRTLChar(prevChar)) {
  138. result = true;
  139. break;
  140. }
  141. else if(PRMT_BidiUtils.isLatinChar(prevChar)) {
  142. break;
  143. }
  144. i--;
  145. }
  146. return result;
  147. },
  148. /**
  149. * This function determines the positions where we should insert the LRM marker for correct display
  150. * of the structured text (STT)
  151. */
  152. parseSTT : function(str, ce_type){
  153. var i,i1;
  154. var delimiters;
  155. var previous = -1;
  156. var segmentsPointers = [];
  157. var sp_len = 0;
  158. if(ce_type == "FILEPATH"){
  159. delimiters = "/\\:.";
  160. for (i = 0; i < str.length; i++) {
  161. if ((delimiters.indexOf(str.charAt(i)) >= 0) && PRMT_BidiUtils.isCharBeforeRTLChar(str,i,previous)){
  162. previous = i;
  163. segmentsPointers[sp_len] = i;
  164. sp_len++;
  165. }
  166. }
  167. }
  168. return segmentsPointers;
  169. },
  170. /**
  171. * This function inserts the LRM char at the positions returned by the previous method
  172. */
  173. insertMarkers : function(str, ce_type) {
  174. var segmentsPointers = PRMT_BidiUtils.parseSTT(str, ce_type);
  175. var buf = str;
  176. shift = 0;
  177. var n;
  178. var marker = PRMT_BidiUtils.BIDI_CHAR_LRM;
  179. for (var i = 0; i< segmentsPointers.length; i++) {
  180. n = segmentsPointers[i];
  181. if(n != null){
  182. preStr = buf.substring(0, n + shift);
  183. postStr = buf.substring(n + shift, buf.length);
  184. buf = preStr + marker + postStr;
  185. shift++;
  186. }
  187. }
  188. return buf;
  189. },
  190. /**
  191. * This function inserts the LRM markers in the fake input when the focus is on the true input
  192. */
  193. onFileFocus : function(inputFile, id, ce_type) {
  194. var fakeObj = document.getElementById(id);
  195. fakeObj.value = PRMT_BidiUtils.insertMarkers(inputFile.value, ce_type);
  196. },
  197. /**
  198. * This function inserts the LRM markers in the fake input when the true input has changed
  199. */
  200. onFileChange : function(inputFile, id, ce_type) {
  201. var fakeObj = document.getElementById(id);
  202. fakeObj.value = PRMT_BidiUtils.insertMarkers(inputFile.value, ce_type);
  203. fakeObj.focus();
  204. },
  205. /**
  206. * This function reacts on inserting chars in the fake input
  207. */
  208. onFakeKeyDown : function(event, id) {
  209. event = (event) ? event : ((window.event) ? window.event : "");
  210. var kCode = event.keyCode;
  211. if (event.altKey || event.ctrlKey || kCode == PRMT_BidiUtils.VK_SHIFT) {
  212. return true;
  213. }
  214. else if (!(kCode == PRMT_BidiUtils.VK_HOME || kCode == PRMT_BidiUtils.VK_END || kCode == PRMT_BidiUtils.VK_LEFT || kCode == PRMT_BidiUtils.VK_RIGHT)) {
  215. PRMT_BidiUtils.focusElement(id);
  216. return false;
  217. }
  218. else {
  219. return true;
  220. }
  221. },
  222. /**
  223. * This function focuses on the element whose id is given in parameter
  224. */
  225. focusElement : function(id) {
  226. var elem = document.getElementById(id);
  227. elem.focus();
  228. return false;
  229. },
  230. /**
  231. * This function handles the copy operation
  232. * Basically we should remove the LRM markers from the text contained in the clipboard
  233. */
  234. processCopy : function (obj){
  235. var text = "";
  236. try{
  237. if ( window.navigator.appName == "Microsoft Internet Explorer" ) {
  238. var w = obj.document.parentWindow;
  239. var e = w.event;
  240. var range = obj.document.selection.createRange();
  241. text = range.text;
  242. }
  243. else {
  244. text = obj.document.getSelection();
  245. }
  246. var textToClipboard = PRMT_BidiUtils.removeMarkers(text);
  247. if (window.clipboardData) {
  248. window.clipboardData.setData("Text", textToClipboard);
  249. e.returnValue = false;
  250. }
  251. }
  252. catch(e)
  253. {
  254. var v_sMsg = "";
  255. if ( e && e.name )
  256. {
  257. v_sMsg += e.name + "\n";
  258. }
  259. if ( e && e.message )
  260. {
  261. v_sMsg += e.message;
  262. }
  263. if ( v_sMsg )
  264. {
  265. alert( v_sMsg );
  266. }
  267. }
  268. },
  269. /**
  270. * This function removes all the Bidi markers in a string
  271. */
  272. removeMarkers : function (str){
  273. var result = str.replace(/\u200E/g,"");
  274. result = result.replace(/\u200F/g,"");
  275. result = result.replace(/\u202A/g,"");
  276. result = result.replace(/\u202B/g,"");
  277. return result.replace(/\u202C/g,"");
  278. },
  279. /**
  280. * This function formats a structured text of type FILEPATH
  281. */
  282. formatFilePath : function (str){
  283. var result = PRMT_BidiUtils.insertMarkers(str, 'FILEPATH');
  284. return PRMT_BidiUtils.enforceBidiDirection(result, PRMT_BidiUtils.BIDI_TXTDIR_LTR);
  285. }
  286. };