如何以编程方式检查浏览器是否将某些字符视为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';
}
}
但是,显然,在Chrome和Opera开始支持Unicode 5.2之后,这会降低脚本的可用性。
答案 0 :(得分:19)
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);
};
答案 1 :(得分:6)
我意识到在原问题被提出并回答之后已经有一段时间了,但我发现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);
};
可能有一些方法可以加速上述正则表达式。使用具有延迟量词的否定字符类似乎有助于提高速度(在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);
};
答案 2 :(得分:2)
首先解决标题中的问题:
JavaScript中没有工具可用于访问字符的Unicode属性。您需要为此目的找到一个库或服务(我担心如果您需要可靠的东西可能会很困难)或者从Unicode字符“database”(特定格式的文本文件集合)中提取相关信息并编写自己的代码来使用它。
然后是留言体中的问题:
这似乎更加绝望。但是,对于知识渊博且知道Avestan的有限数量的用户而言,这可能是一件事,也许在正确的方向性上显示一串Avestan字符以及它们的图像并要求用户点击一下也不会太糟糕。如果订单错误,按钮。你可以将这个选择保存在一个cookie中,这样用户只需要这样做一次(每个浏览器;虽然它应该是相对短暂的cookie,因为浏览器可能会更新)。
答案 3 :(得分:2)
感谢您的评论,但似乎我自己也这样做了:
function is_script_rtl(t) {
var d, s1, s2, bodies;
//If the browser doesn’t support this, it probably doesn’t support Unicode 5.2
if (!("getBoundingClientRect" in document.documentElement))
return false;
//Set up a testing DIV
d = document.createElement('div');
d.style.position = 'absolute';
d.style.visibility = 'hidden';
d.style.width = 'auto';
d.style.height = 'auto';
d.style.fontSize = '10px';
d.style.fontFamily = "'Ahuramzda'";
d.appendChild(document.createTextNode(t));
s1 = document.createElement("span");
s1.appendChild(document.createTextNode(t));
d.appendChild(s1);
s2 = document.createElement("span");
s2.appendChild(document.createTextNode(t));
d.appendChild(s2);
d.appendChild(document.createTextNode(t));
bodies = document.getElementsByTagName('body');
if (bodies) {
var body, r1, r2;
body = bodies[0];
body.appendChild(d);
var r1 = s1.getBoundingClientRect();
var r2 = s2.getBoundingClientRect();
body.removeChild(d);
return r1.left > r2.left;
}
return false;
}
使用示例:
Avestan in <script>document.write(is_script_rtl('') ? "RTL" : "LTR")</script>,
Arabic is <script>document.write(is_script_rtl('العربية') ? "RTL" : "LTR")</script>,
English is <script>document.write(is_script_rtl('English') ? "RTL" : "LTR")</script>.
似乎有效。 :)
答案 4 :(得分:2)
希伯来语和阿拉伯语的测试(我知道唯一的现代RTL语言/字符集,从右到左流动,除了我没有研究过的任何与波斯语相关的内容):
/[\u0590-\u06FF]/.test(textarea.value)
更多的研究表明了以下几点:
/[\u0590-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(textarea.value)