【问题标题】:JavaScript Unicode's length (astral symbols)JavaScript Unicode 的长度(星体符号)
【发布时间】:2018-07-24 02:42:50
【问题描述】:

我有一个< input type="text" >(在 HTML 中),每次我添加一个字符时,我都会做一个 if text.length < x {...}(在 JavaScript 中)。

问题在于 Unicode 特殊字符/星体符号(\u{.....},具有超过 4 个十六进制/非 BMP 字符的符号)“存储为两个代码单元,因此长度属性将返回 2 而不是 1。”

(https://mixmax.com/blog/unicode-woes-in-javascript)

我希望能够为所有符号获得 1 或 2,只要它不将一些与 1 和一些与 2 混合,因为我必须对可视文本的大小有一个工作限制。

我认为解决方案在这里:https://mathiasbynens.be/notes/javascript-unicode#accounting-for-astral-symbols,但我不确定如何使用它。

我的 if 是这样的:

if(document.getElementById("1").value.length<16){

编辑(它正在工作!):

<html>
    <head>
        <style>
            input{background:white;border:1px solid;height:30;outline-color:black;position:absolute;top:389;width:30}
        </style>
        <script>
            <!--
                function Add(symbol){
                    if (countSymbols(document.getElementById("1").value)<16) {
                        document.getElementById("1").value+=symbol}
                    if(document.getElementById("1").value.length==16 && document.getElementById("1").value=="\u{1F4BB}\u{1F3AE}\u{1F3C3}\u{1F525}\u2764\u{1D7CF}\u{1D7D1}\u{1F4B0}\u2757"){
                        document.getElementById("1").style.background="#00BB00"}
                    if(document.getElementById("1").value.length==16 && document.getElementById("1").value!="\u{1F4BB}\u{1F3AE}\u{1F3C3}\u{1F525}\u2764\u{1D7CF}\u{1D7D1}\u{1F4B0}\u2757"){
                        document.getElementById("1").style.background="#BB0000"}
                }
                function countSymbols(string) {
                    var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
                    return string
                    // Replace every surrogate pair with a BMP symbol.
                    .replace(regexAstralSymbols, '_')
                    // …and *then* get the length.
                    .length;
                }
            //-->
        </script>
    </head>
    <body>
        <input readOnly="true" id="1" style="left:573;outline:0;padding:5 8;top:356;width:294">
        <input onclick="Add('\u{1F4BB}')" style="left:573" type="button" value="&#128187">
        <input onclick="Add('\u{1F3AE}')" style="left:606" type="button" value="&#127918">
        <input onclick="Add('\u{1F3C3}')" style="left:639" type="button" value="&#127939">
        <input onclick="Add('\u{1F525}')" style="left:672" type="button" value="&#128293">
        <input onclick="Add('\u2764')" style="left:705" type="button" value="&#10084">
        <input onclick="Add('\u{1D7CF}')" style="left:738" type="button" value="&#120783">
        <input onclick="Add('\u{1D7D1}')" style="left:771" type="button" value="&#120785">
        <input onclick="Add('\u{1F4B0}')" style="left:804" type="button" value="&#128176">
        <input onclick="Add('\u2757')" style="left:837" type="button" value="&#10071">
    </body>
</html>

【问题讨论】:

  • “视觉文本”...?我希望这并不意味着您要限制 显示宽度 (显示时文本将占用多少像素)?因为用这种方法是不可能的。如果偏离主题,请忽略此评论。
  • 可视文本 = 您可以看到的符号长度/非 bmp。就像,文本(框)中只有最大长度 = 9 个字符。
  • 例如,???????? 的长度是 4,但我的意思是可视文本 = 2。
  • 我可以加倍长度检查/如果但问题是文本(框)可以有这样的东西:????2????7 长度为 2+1+ 2+1=6,但视觉是 4。

标签: javascript html


【解决方案1】:

我认为您已经完成了大部分研究,您只需将所有这些放在一起:

采用您的链接提供的功能:

function countSymbols(string) {
    var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
    return string
        // Replace every surrogate pair with a BMP symbol.
        .replace(regexAstralSymbols, '_')
        // …and *then* get the length.
        .length;
}

你的 if 应该是

if (countSymbols(document.getElementById("1").value)<16) { ...}

例如:countSymbols('?2?7') 返回 4

这里有一个小例子:https://jsfiddle.net/q7g9qtk7/

更新:您也可以使用Array.from(IE、Chrome 和 Firefox 的 polyfilling 已经支持它),它接受一个字符串并将其拆分为每个字符,无论它有多长:

Array.from('?2?7') //returns ["?", "2", "?", "7"]

所以你的功能可能是

function countSymbols(string) {
       return Array.from(string).length;
}

【讨论】:

  • 嗯,这应该可以,但我试过了,它没有返回任何东西。我认为函数 countSymbols 没有按预期工作。
  • 在记事本中,我使用 \u{1F3C3}2\u{1F525}7 而不是 ?2?7,因为我无法保存 unicode。 if 不起作用,我最后尝试了它,但它不起作用(document.getElementById("1").value=countSymbols(document.getElementById("1").value.length
  • 那行得通,我会看看我在代码中做错了什么。谢谢。
  • 你忘记了正则表达式...我在函数中添加了使其“可导出”;)
  • [...'???'].length === 3
猜你喜欢
  • 1970-01-01
  • 2022-11-04
  • 2021-12-03
  • 2013-04-03
  • 1970-01-01
  • 2015-03-07
  • 2017-12-28
  • 1970-01-01
相关资源
最近更新 更多