获取jQuery ui自动完成功能仅适用于@mentions

时间:2013-06-10 15:27:27

标签: javascript jquery jquery-ui autocomplete jquery-ui-autocomplete

我已经看了几个问题,例如https://stackoverflow.com/a/7222592/2332251

我仍然无法将其与我的代码进行协调。

目前,当我开始输入时,以下内容非常适合搜索用户名。

$(function() {
    $("#appendedInputButton").autocomplete({
        minLength: 2,  
    source: "searchusers.php" 
        });                
});

searchusers.php中的函数输出数据库中的用户名。

正如我所说,我无法让其他@mention解决方案为我工作。我曾尝试复制其他解决方案并交换我的详细信息,但似乎没有任何效果。

因此...

  1. 我需要对当前的自动完成脚本执行哪些操作才能使其仅加载 当我最初输入'@'符号时?
  2. 我真的希望能够在我的帖子中有多个@mentions
  3. (可选)当自动填充建议用户名时,当我从列表中选择用户名时,我希望它出现在我的帖子中,@ symbol仍然附加在用户名的前面,例如“你好@john,@符号仍然附在你的用户名”
  4. 如果您需要更多信息,请发表评论,我会提供更多信息:)

    编辑我真的不确定使其工作的语法。例如,使用我上面发布的示例答案,我提出了(但它不起作用):

    function split(val) {
    return val.split(/@\s*/);
    }
    
    function extractLast(term) {
        return split(term).pop();
    }
    
    function getTags(term, callback) {
        $.ajax({
            url: "searchusers.php",
            data: {
                filter: term,
                pagesize: 5
            },
            type: "POST",
            success: callback,
            jsonp: "jsonp",
            dataType: "jsonp"
        });    
    }
    
    $(document).ready(function() {
    
    $("#appendedInputButton")
    // don't navigate away from the field on tab when selecting an item
    .bind("keydown", function(event) {
        if (event.keyCode === $.ui.keyCode.TAB && $(this).data("autocomplete").menu.active) {
    
            event.preventDefault();
        }
    }).autocomplete({
        source: function(request, response) {
            if (request.term.indexOf("@") >= 0) {
                $("#loading").show();
                getTags(extractLast(request.term), function(data) {
                    response($.map(data.tags, function(el) {
                        return {
                            value: el.name,
                            count: el.count
                        }
                    }));
                    $("#loading").hide();                    
                });
            }
        },
        focus: function() {
            // prevent value inserted on focus
            return false;
        },
        select: function(event, ui) {
            var terms = split(this.value);
            // remove the current input
            terms.pop();
            // add the selected item
            terms.push(ui.item.value);
            // add placeholder to get the comma-and-space at the end
            terms.push("");
            this.value = terms.join("");
            return false;
        }
    }).data("autocomplete")._renderItem = function(ul, item) {
        return $("<li>")
            .data("item.autocomplete", item)
            .append("<a>" + item.label + "&nbsp;<span class='count'>(" + item.count + ")</span></a>")
            .appendTo(ul);
    };
    });
    

    我在哪里插入searchusers.php,#attachInputButton和其他具体信息?我希望这是有道理的。

2 个答案:

答案 0 :(得分:4)

我会根据我的评论形成一个答案。

首先让我们回顾一下要求清单:

  • @符号
  • 开头的自动填充用户名
  • 使用@符号
  • 添加用户名
  • 文本中的多个@mentions
  • 在文本中的任何位置编辑任何@mention

实现最后一个要求我们需要一些我在stackoverflow上找到的魔术函数:

另外,要检测文本中某处的用户名,我们需要为用户名定义一些约束。我假设它只能包含字母和数字,并用\w+模式进行测试。

您可以在这里找到的实时演示http://jsfiddle.net/AU92X/6/它总是返回2行而不进行过滤只是为了演示行为。在下面的列表中,我将问题中的原始getTags函数放在了我看来很好。虽然我不知道searchusers.php是如何运作的。

function getCaretPosition (elem) {

  // Initialize
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    elem.focus ();

    // To get cursor position, get empty selection range
    var 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 support
  else if (elem.selectionStart || elem.selectionStart == '0')
    iCaretPos = elem.selectionStart;

  // Return results
  return (iCaretPos);
}

function setCaretPosition(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();
        }
    }
}

function getTags(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 focus
            return false;
        },
        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);
            }    
            return false;
        }
    }).data("ui-autocomplete")._renderItem = function(ul, item) {
        return $("<li>")
            .data("ui-autocomplete-item", item)
            .append("<a>" + item.label + "&nbsp;<span class='count'>(" + item.count + ")</span></a>")
            .appendTo(ul);
    };
});

答案 1 :(得分:0)

我无法添加评论,所以我只想将其添加为答案。

我尝试了您提供的代码段并且效果很好。我唯一的问题是在编辑提及时。我决定从提及的中间编辑,自动完成显示,我成功选择了一个项目。只是 - 它没有删除前面提到的其余内容,只删除了光标位置之前的字母。

所以我添加了一些额外的东西:

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);
    }    
    return false;
}

我稍微改变了选择功能以覆盖剩菜。现在,它正在搜索下一个“”事件,并将其前面的所有内容的长度添加到替换值。

希望这会有所帮助:)