根据光标位置resize jQuery autocomplete UI

Resize jQuery autocomplete UI according to the cursor position

我正在为我自己的低级程序创建自动完成功能 executor.I 需要像在 VScode 和其他 IDE 中那样获取字母表附近的自动完成值。但是我在调​​整它的大小时遇到​​了问题。一旦我在文本区域中为它附近的每个单词输入单词,我就需要得到这个框。

这是我的 html 代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
  <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
  <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
  <style>
    .ui-autocomplete {
    width:140px !important;
    top: 50px !important;
}
  </style>
  <script>
 $(function () {
      console.log("hi");
      var availableTags = ["SET","ADD","MUL","SUB","DIV","MOD","LOOP","ENDLOOP","IF","ENDIF","ELSE","ENDELSE","END"];
      function split( val ) {
        return val.split( / \s*/ );
      }
      function extractLast( term ) {
        return split( term ).pop();
      }
   

      $( "#tags" ).bind( "keydown", function( event ) {
            //can also use this to track when user presses SPACE
          if(event.which===32)
                 $('#characterSpan').html($(this).val());
          
          if ( event.keyCode === $.ui.keyCode.TAB &&
              $( this ).data( "autocomplete" ).menu.active ) {
            event.preventDefault();
          }
        }),
        $( "#tags" ).autocomplete({
          minLength: 1,
          source: function( request, response ) {
            response( $.ui.autocomplete.filter(
              availableTags, extractLast( request.term ) ) );
          },
          focus: function() {
            return false;
          },
          select: function( event, ui ) {
            var terms = split( this.value );
            terms.pop();
            terms.push( ui.item.value );
            terms.push( " " );
            this.value = terms.join(" ");
            //when item selected, add current value to span
            //$('#characterSpan').html($(this).val());
            return false;
          },
         open: function( event, ui ) {
              
               $('.ui-autocomplete.ui-menu');
          },
          open: function() {
            var position = window.getSelection().getRangeAt(0).startOffset;
            var cursorPos= $("#tags").prop('selectionStart');
            $("ul.ui-menu").width();
    }
         });
    
});

  </script>
  <title>Document</title>
</head>
<body>
  <div id="menu-container" style="position:absolute; width: 500px;">
    <label for="tags">Tag programming languages: </label>
    <textarea id="tags" rows="20" cols="70"></textarea>
    <span id="characterSpan" style="visibility: hidden;"></span>
  </div>
</body>
</html>

在这些行中:

$(".ui-autocomplete").css("left", getCursorPos($("#tags")[0]) * 7.5 + 7.5 + "px");
$(".ui-autocomplete").css("top", getLineNumber($("#tags")[0]) * 15 + 30 + "px");

我假设起始水平位置为 7.5px,每个字母的宽度为 7.5px,起始位置为垂直 30px,每个字母的高度为 15px。我还使用了 this 答案中的两个函数来获取光标位置。

function getLineNumber(tArea) {
        return tArea.value.substr(0, tArea.selectionStart).split("\n").length;
      }

      function getCursorPos(me) {
        var el = $(me).get(0);
        var pos = 0;
        if ("selectionStart" in el) {
          pos = el.selectionStart;
        } else if ("selection" in document) {
          el.focus();
          var Sel = document.selection.createRange();
          var SelLength = document.selection.createRange().text.length;
          Sel.moveStart("character", -el.value.length);
          pos = Sel.text.length - SelLength;
        }
        var ret = pos - prevLine(me);
        return ret;
      }

      function prevLine(me) {
        var lineArr = me.value.substr(0, me.selectionStart).split("\n");

        var numChars = 0;

        for (var i = 0; i < lineArr.length - 1; i++) {
          numChars += lineArr[i].length + 1;
        }

        return numChars;
      }

      $(function () {
        console.log("hi");
        var availableTags = [
          "SET",
          "ADD",
          "MUL",
          "SUB",
          "DIV",
          "MOD",
          "LOOP",
          "ENDLOOP",
          "IF",
          "ENDIF",
          "ELSE",
          "ENDELSE",
          "END",
        ];
        function split(val) {
          return val.split(/ \s*/);
        }
        function extractLast(term) {
          return split(term).pop();
        }

        $("#tags").bind("keydown", function (event) {
          //can also use this to track when user presses SPACE
          if (event.which === 32) $("#characterSpan").html($(this).val());

          if (event.keyCode === $.ui.keyCode.TAB && $(this).data("autocomplete").menu.active) {
            event.preventDefault();
          }
        }),
          $("#tags").autocomplete({
            minLength: 1,
            source: function (request, response) {
              response($.ui.autocomplete.filter(availableTags, extractLast(request.term)));
              $(".ui-autocomplete").css("left", getCursorPos($("#tags")[0]) * 7.5 + 7.5 + "px");
              $(".ui-autocomplete").css("top", getLineNumber($("#tags")[0]) * 15 + 30 + "px");
            },
            focus: function () {
              return false;
            },
            select: function (event, ui) {
              /* var terms = split(this.value);
              terms.pop();
              terms.push(ui.item.value);
              terms.push(" ");
              this.value = terms.join(" "); */
              this.value = this.value + ui.item.value;
              return false;
            },
            open: function (event, ui) {
              $(".ui-autocomplete.ui-menu");
            },
            open: function () {
              var position = window.getSelection().getRangeAt(0).startOffset;
              var cursorPos = $("#tags").prop("selectionStart");
              $("ul.ui-menu").width();
            },
          });
      });
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" />
    <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
    <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <style>
      .ui-autocomplete {
        width: 140px !important;
        /* top: 50px !important; */
      }
    </style>
    <title>Document</title>
  </head>
  <body>
    <div id="menu-container" style="position: absolute; width: 500px">
      <label for="tags">Tag programming languages: </label>
      <textarea id="tags" rows="20" cols="70"></textarea>
      <span id="characterSpan" style="visibility: hidden"></span>
    </div>
  </body>
</html>