Getting Jquery Ui Autocomplete To Work With @mentions Only
Solution 1:
I will form an answer based on my comments.
First of all lets review the list of requirements:
- autocomplete usernames started with
@
symbol - prepend usernames with
@
symbol - multiple @mentions in a text
- edit any @mention anywhere in a text
to implement the last requirement we need some magic functions that i found on stackoverflow:
getCaretPosition
- https://stackoverflow.com/a/2897229/2335291setCaretPosition
- https://stackoverflow.com/a/512542/2335291
Also to detect a username somewhere in the text we need to define some constraints for usernames. I assume that it can have only letters and numbers and test it with \w+
pattern.
The live demo you can find here http://jsfiddle.net/AU92X/6/ It always returns 2 rows without filtering just to demonstrate the behavior. In the listing below i've put the original getTags
function from the question as it looks fine for me. Although i have no idea how searchusers.php
works.
functiongetCaretPosition (elem) {
// Initializevar iCaretPos = 0;
// IE Supportif (document.selection) {
// Set focus on the element
elem.focus ();
// To get cursor position, get empty selection rangevar oSel = document.selection.createRange ();
// Move selection start to 0 position
oSel.moveStart ('character', -elem.value.length);
// The caret position is selection length
iCaretPos = oSel.text.length;
}
// Firefox supportelseif (elem.selectionStart || elem.selectionStart == '0')
iCaretPos = elem.selectionStart;
// Return resultsreturn (iCaretPos);
}
functionsetCaretPosition(elem, caretPos) {
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
}
}
functiongetTags(term, callback) {
$.ajax({
url: "searchusers.php",
data: {
filter: term,
pagesize: 5
},
type: "POST",
success: callback,
jsonp: "jsonp",
dataType: "jsonp"
});
}
$(document).ready(function() {
$("#appendedInputButton").autocomplete({
source: function(request, response) {
var term = request.term;
var pos = getCaretPosition(this.element.get(0));
var substr = term.substring(0, pos);
var lastIndex = substr.lastIndexOf('@');
if (lastIndex >= 0){
var username = substr.substr(lastIndex + 1);
if (username.length && (/^\w+$/g).test(username)){
getTags(username, function(data) {
response($.map(data.tags, function(el) {
return {
value: el.name,
count: el.count
}
}));
});
return;
}
}
response({});
},
focus: function() {
// prevent value inserted on focusreturnfalse;
},
select: function(event, ui) {
var pos = getCaretPosition(this);
var substr = this.value.substring(0, pos);
var lastIndex = substr.lastIndexOf('@');
if (lastIndex >= 0){
var prependStr = this.value.substring(0, lastIndex);
this.value = prependStr + '@' + ui.item.value + this.value.substr(pos);
setCaretPosition(this, prependStr.length + ui.item.value.length + 1);
}
returnfalse;
}
}).data("ui-autocomplete")._renderItem = function(ul, item) {
return $("<li>")
.data("ui-autocomplete-item", item)
.append("<a>" + item.label + " <span class='count'>(" + item.count + ")</span></a>")
.appendTo(ul);
};
});
Solution 2:
I cannot add a comment, so I'm just going to add this as an answer.
I tried the code snippet you've provided and it worked great. The only problem I had was while editing the mention. I decided to edit from the middle of the mention, the autocomplete showed and I selected an item successfully. Only - it didn't delete the rest of the previous mention, only the letters before the cursor's position.
So I added something extra:
select: function(event, ui) {
var pos = comments.init.getCaretPosition(this);
var substr = this.value.substring(0, pos);
var lastIndex = substr.lastIndexOf('@');
var afterPosString = this.value.substring(pos, this.value.length);
var leftovers = afterPosString.indexOf(' ');
if (leftovers == -1)
leftovers = afterPosString.length;
if (lastIndex >= 0){
var prependStr = this.value.substring(0, lastIndex);
this.value = prependStr + '@' + ui.item.value + this.value.substr(pos + leftovers);
comments.init.setCaretPosition(this, prependStr.length + ui.item.value.length + 1);
}
returnfalse;
}
I changed the select function a bit to cover the leftovers. Now, it's searching for the next " " occurrence and adds the length of everything before it to the replaced value.
Hope this helps :)
Post a Comment for "Getting Jquery Ui Autocomplete To Work With @mentions Only"