Search code examples
javascriptjqueryjquery-uicoffeescriptjquery-ui-autocomplete

Append jQuery autocomplete data to textarea content instead of overwriting it


I am trying to make a @ other people function in my rails app, just like stackoverflow:

enter image description here

I've almost finished this function, but I encounter problems, the jQuery auto-compelete data replace my textarea content, not append.

enter image description here

Coffeescript:

find_at_sign = ->
  if $("#tags").val().split('').pop() == "@"
    id = $("#tags").data("article-id")
    $("#tags").autocomplete
      source:  '/articles/' + id + '/autocomplete.json'
      minLength: 1

$ ->
  $(document).on("input", "#tags",
  -> find_at_sign())

Article Controller:

  def autocomplete
    @articles = Article.find_by(id: params[:article_id])
    @commentor_names = @articles.comments.map(&:name).uniq
    respond_to do |format|
      format.html
      format.json {
        render json: @commentor_names
      }
    end
  end

form_html.erb:

 <div class="form-group ui-widget">
    <div class="col-sm-5">
      <%= f.text_area :content, rows: 5, placeholder: '说点什么...', 
          class: 'form-control', id: "tags", 'data-article-id': @article.id.to_s %>
    </div>
  </div>

I tried to use append method, but doesn't work:

$("#tags").append(${this).autocomplete
  source:  '/articles/' + id + '/autocomplete.json'
  minLength: 1)

Any help is appreciate!


Solution

  • Here is my half-hearted attempt at this, based on this example. The important bits are as follows:

    • Cancel the built-in focus event which attempts to overwrite the value inside textbox
    • Cancel the built-in select event and configure it to append the selected @name inside textbox instead of overwriting it
    • Provide a custom source function which extracts the last @name from the textbox and looks up that name and returns matching names

    var namelist = [
      "Adam",
      "Adrian",
      "Andrew",
      "Charles",
      "Daniel",
      "David",
      "Evan",
      "Henry",
      "Ian",
      "Jack",
      "James",
      "John",
      "Joseph",
      "Justin",
      "Kevin",
      "Michael",
      "Parker",
      "Robert",
      "Thomas",
      "William"
    ];
    $(function() {
      $("#message").autocomplete({
        source: function(request, response) {
          var match = request.term.match(/@(\w*)$/);
          var names = match ? $.ui.autocomplete.filter(namelist, match[1]) : [];
          response(names)
        },
        focus: function(event) {
          event.preventDefault();
        },
        select: function(event, ui) {
          event.preventDefault();
          this.value = this.value.replace(/@(\w*)$/, "@" + ui.item.value)
        }
      })
    });
    @import url("https://code.jquery.com/ui/1.11.4/themes/ui-darkness/jquery-ui.min.css");
    
    body {
      font: smaller sans-serif;
    }
    textarea {
      box-sizing: border-box;
      width: 100%;
      height: 5em;
    }
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    
    
    <p>Enter some text or @name</p>
    <textarea id="message"></textarea>