'Resize jQuery autocomplete UI according to the cursor position
I'm creating autocomplete feature for my own low level program executor.I need to get the autocomplete values near the alphabet typed like in VScode and other IDEs. But I have a problem with resizing it. I need to get the box once I type in the word in textarea for each and every word near it.
Here is my html code
<!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>
Solution 1:[1]
In these lines:
$(".ui-autocomplete").css("left", getCursorPos($("#tags")[0]) * 7.5 + 7.5 + "px");
$(".ui-autocomplete").css("top", getLineNumber($("#tags")[0]) * 15 + 30 + "px");
I'm assuming 7.5px as starting horizontal position and 7.5px the width of each letter, vertically 30px as starting position and 15px the height of each letter. I also used two functions from this answer to get the cursor position.
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>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | user2495207 |