Kry*_*nik 15 javascript unicode bidi right-to-left
如何以编程方式检查浏览器是否将某些字符视为JavaScript中的RTL?
也许创建一些透明的DIV并查看文本的放置位置?
一点背景.Unicode 5.2增加了Avestan字母表支持.因此,如果浏览器支持Unicode 5.2,它会将U + 10B00等字符视为RTL(目前只有Firefox支持).否则,它会将这些字符视为LTR,因为这是默认值.
我如何以编程方式检查这个?我正在写一个Avestan输入脚本,如果浏览器太笨,我想覆盖bidi方向.但是,如果浏览器确实支持Unicode,则不应覆盖bidi设置(因为这将允许混合Avestan和Cyrillic).
我目前这样做:
var ua = navigator.userAgent.toLowerCase();
if (ua.match('webkit') || ua.match('presto') || ua.match('trident')) {
var input = document.getElementById('orig');
if (input) {
input.style.direction = 'rtl';
input.style.unicodeBidi = 'bidi-override';
}
}
Run Code Online (Sandbox Code Playgroud)
但是,显然,在Chrome和Opera开始支持Unicode 5.2之后,这会使脚本不太可用.
vsy*_*ync 20
function isRTL(s){
var ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF',
rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC',
rtlDirCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']');
return rtlDirCheck.test(s);
};
Run Code Online (Sandbox Code Playgroud)
在原始问题被问及回答之后我意识到这已经有一段时间了,但我发现vsync的更新非常有用,只是想添加一些观察.我会在评论中加上这个答案,但我的声誉还不够高.
而不是从行的开头搜索零个或多个非LTR字符然后搜索一个RTL字符的正则表达式,从行的开头搜索零或更多弱/中性字符然后更有意义一个RTL角色?否则,您可能会不必要地匹配许多RTL字符.我欢迎对我的弱/中立角色群进行更彻底的检查,因为我只是使用了对LTR和RTL组合字符组合的否定.
此外,LTR/RTL标记,嵌入,覆盖等字符是否应包含在相应的字符分组中?
我认为最后的代码看起来应该是这样的:
function isRTL(s){
var weakChars = '\u0000-\u0040\u005B-\u0060\u007B-\u00BF\u00D7\u00F7\u02B9-\u02FF\u2000-\u2BFF\u2010-\u2029\u202C\u202F-\u2BFF',
rtlChars = '\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC',
rtlDirCheck = new RegExp('^['+weakChars+']*['+rtlChars+']');
return rtlDirCheck.test(s);
};
Run Code Online (Sandbox Code Playgroud)
可能有一些方法可以加速上述正则表达式.使用带有惰性量词的否定字符类似乎有助于提高速度(在http://regexhero.net/tester/?id=6dab761c-2517-4d20-9652-6d801623eeec上测试,网站需要Silverlight 5)
另外,如果字符串的方向性未知,我的猜测是,对于大多数情况,字符串将是LTR而不是RTL,isLTR如果是这种情况,创建函数会更快地返回结果但是正如OP要求的那样isRTL,将提供isRTL函数:
function isRTL(s){
var rtlChars = '\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC',
rtlDirCheck = new RegExp('^[^'+rtlChars+']*?['+rtlChars+']');
return rtlDirCheck.test(s);
};
Run Code Online (Sandbox Code Playgroud)
感谢您的评论,但似乎我自己已经这样做了:
\n\nfunction is_script_rtl(t) {\n var d, s1, s2, bodies;\n\n //If the browser doesn\xe2\x80\x99t support this, it probably doesn\xe2\x80\x99t support Unicode 5.2\n if (!("getBoundingClientRect" in document.documentElement))\n return false;\n\n //Set up a testing DIV\n d = document.createElement(\'div\');\n d.style.position = \'absolute\';\n d.style.visibility = \'hidden\';\n d.style.width = \'auto\';\n d.style.height = \'auto\';\n d.style.fontSize = \'10px\';\n d.style.fontFamily = "\'Ahuramzda\'";\n d.appendChild(document.createTextNode(t));\n\n s1 = document.createElement("span");\n s1.appendChild(document.createTextNode(t));\n d.appendChild(s1);\n\n s2 = document.createElement("span");\n s2.appendChild(document.createTextNode(t));\n d.appendChild(s2);\n\n d.appendChild(document.createTextNode(t));\n\n bodies = document.getElementsByTagName(\'body\');\n if (bodies) {\n var body, r1, r2;\n\n body = bodies[0];\n body.appendChild(d);\n var r1 = s1.getBoundingClientRect();\n var r2 = s2.getBoundingClientRect();\n body.removeChild(d);\n\n return r1.left > r2.left;\n }\n\n return false; \n}\nRun Code Online (Sandbox Code Playgroud)\n\n使用示例:
\n\nAvestan in <script>document.write(is_script_rtl(\'\') ? "RTL" : "LTR")</script>,\nArabic is <script>document.write(is_script_rtl(\'\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9\') ? "RTL" : "LTR")</script>,\nEnglish is <script>document.write(is_script_rtl(\'English\') ? "RTL" : "LTR")</script>.\nRun Code Online (Sandbox Code Playgroud)\n\n似乎有效。:)
\n| 归档时间: |
|
| 查看次数: |
9657 次 |
| 最近记录: |