var app = angular.module('plunker', ['ui.mention']);
app.run(function($rootScope) {
  $rootScope.post = {
    message: "hi there @[bob barker:11123] @[kenny logins:123ab-123]"
  };
})
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  //$scope.$mentions.mentions = [{"first":"bob","last":"barker","id":11123}];
});
app.directive('mentionExample', function() {
  return {
    require: 'uiMention',
    link: function link($scope, $element, $attrs, uiMention) {
      /**
       * $mention.findChoices()
       *
       * @param  {regex.exec()} match    The trigger-text regex match object
       * @todo Try to avoid using a regex match object
       * @return {array[choice]|Promise} The list of possible choices
       */

      uiMention.findChoices = function(match, mentions) {
        return choices
          // Remove items that are already mentioned
          .filter(function(choice) {
            return !mentions.some(function(mention) {
              return mention.id === choice.id;
            });
          })
          // Matches items from search query
          .filter(function(choice) {
            return ~(choice.first + ' ' + choice.last).indexOf(match[1]);
          });
      };
      
      uiMention.mentions.push(choices[0], choices[1]);
    }
  };
});

var choices = [{
  first: 'bob',
  last: 'barker',
  id: 11123
}, {
  first: 'kenny',
  last: 'logins',
  id: '123ab-123'
}, {
  first: 'kyle',
  last: 'corn',
  id: '123'
}, {
  first: 'steve',
  last: 'rodriguez',
  id: 'hi'
}, {
  first: 'steve',
  last: 'holt',
  id: '0-9'
}, {
  first: 'megan',
  last: 'burgerpants',
  id: 'ab-'
}];
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS - ui-mention </title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
  <script src="mention.min.js"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <h1>UI Mention</h1>
  <h4><a href="https://github.com/angular-ui/ui-mention">Source Code</a></h4>
  <p>
    Facebook-like <strong>@mentions</strong> in your text inputs. Designed with composability in mind.
  </p>

  <div class="mention-container">
    <textarea ui-mention mention-example ng-model="post.message" placeholder="Use @mention to trigger" ng-trim="false"></textarea>
    <div class="mention-highlight"></div>

    <ul ng-if="$mention.choices.length" class="dropdown">
      <li ng-repeat="choice in $mention.choices" ng-class="{active:$mention.activeChoice==choice}">
        <a ng-click="$mention.select(choice)">
          {{::choice.first}} {{::choice.last}}
        </a>
      </li>
    </ul>
  </div>

  <input ng-model="newValue" placeholder="New Value">
  <button ng-click="post.message=newValue">Set Value</button>
  <br>

  <p>
    $mentions.mentions: {{$mention.mentions | json}}
  </p>

  <p>
    ng-model (post.message): {{post.message | json}}
  </p>


</body>

</html>
body {
  font-size: 14px;
  font-family: 'Helvetica'; }

textarea[ui-mention], textarea[ui-mention] + * {
  line-height: 1em;
  font-size: 1rem;
  padding: 5px;
  border: 1px;
  font-family: helvetica;
  font-weight: normal; }

textarea[ui-mention] {
  min-height: 100px;
  width: 100%;
  display: block;
  border: 1px solid;
  z-index: 2;
  position: relative; }
  textarea[ui-mention][ui-mention] {
    background: transparent; }

a {
  color: blue;
  text-decoration: underline;
  cursor: pointer; }
  a:hover {
    color: green; }

.mention-container {
  position: relative; }

.mention-highlight {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 1px;
  padding: 2px;
  z-index: 1;
  color: transparent;
  white-space: pre-wrap;
  border: 1px solid transparent;
  width: 100%; }
  .mention-highlight span {
    border-radius: 3px;
    background: lightblue;
    box-shadow: 0px 0px 0px 1px blue; }

.dropdown {
  position: absolute;
  top: 100%;
  min-width: 150px;
  right: 0;
  background: lightblue;
  list-style: none;
  padding: 0;
  margin: 0; }
  .dropdown a {
    display: block;
    padding: 10px;
    text-decoration: none; }
  .dropdown .active {
    background: lightgreen; }
"use strict";var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[],_n=!0,_d=!1,_e=void 0;try{for(var _s,_i=arr[Symbol.iterator]();!(_n=(_s=_i.next()).done)&&(_arr.push(_s.value),!i||_arr.length!==i);_n=!0);}catch(err){_d=!0,_e=err}finally{try{!_n&&_i["return"]&&_i["return"]()}finally{if(_d)throw _e}}return _arr}return function(arr,i){if(Array.isArray(arr))return arr;if(Symbol.iterator in Object(arr))return sliceIterator(arr,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();angular.module("ui.mention",[]).directive("uiMention",function(){return{require:["ngModel","uiMention"],controller:"uiMention",controllerAs:"$mention",link:function($scope,$element,$attrs,_ref){var _ref2=_slicedToArray(_ref,2),ngModel=_ref2[0],uiMention=_ref2[1];uiMention.init(ngModel)}}}),angular.module("ui.mention").controller("uiMention",["$element","$scope","$attrs","$q","$timeout","$document",function($element,$scope,$attrs,$q,$timeout,$document){function parseContentAsText(content){try{return temp.textContent=content,temp.innerHTML}finally{temp.textContent=null}}var _this2=this;this.delimiter="@",this.searchPattern=this.pattern||new RegExp("(?:\\s+|^)"+this.delimiter+"(\\w+(?: \\w+)?)$"),this.decodePattern=new RegExp(this.delimiter+"[[\\s\\w]+:[0-9a-z-]+]","gi"),this.$element=$element,this.choices=[],this.mentions=[];var ngModel;this.init=function(model){var _this=this;$attrs.ngTrim="false",ngModel=model,ngModel.$parsers.push(function(value){return _this.mentions=_this.mentions.filter(function(mention){if(~value.indexOf(_this.label(mention)))return value=value.replace(_this.label(mention),_this.encode(mention))}),_this.render(value),value}),ngModel.$formatters.push(function(){var value=arguments.length<=0||void 0===arguments[0]?"":arguments[0];return value=value.toString(),_this.mentions=_this.mentions.filter(function(mention){return!!~value.indexOf(_this.encode(mention))&&(value=value.replace(_this.encode(mention),_this.label(mention)),!0)}),value}),ngModel.$render=function(){$element.val(ngModel.$viewValue||""),$timeout(_this.autogrow,!0),_this.render()}};var temp=document.createElement("span");this.render=function(){var html=arguments.length<=0||void 0===arguments[0]?ngModel.$modelValue:arguments[0];return html=(html||"").toString(),html=parseContentAsText(html),_this2.mentions.forEach(function(mention){html=html.replace(_this2.encode(mention),_this2.highlight(mention))}),_this2.renderElement().html(html),html},this.renderElement=function(){return $element.next()},this.highlight=function(choice){return"<span>"+this.label(choice)+"</span>"},this.decode=function(){var value=arguments.length<=0||void 0===arguments[0]?ngModel.$modelValue:arguments[0];return value?value.replace(this.decodePattern,"$1"):""},this.label=function(choice){return choice.first+" "+choice.last},this.encode=function(choice){return this.delimiter+"["+this.label(choice)+":"+choice.id+"]"},this.replace=function(mention){var search=arguments.length<=1||void 0===arguments[1]?this.searching:arguments[1],text=arguments.length<=2||void 0===arguments[2]?ngModel.$viewValue:arguments[2];return text=text.substr(0,search.index+search[0].indexOf(this.delimiter))+this.label(mention)+" "+text.substr(search.index+search[0].length)},this.select=function(){var choice=arguments.length<=0||void 0===arguments[0]?this.activeChoice:arguments[0];return!!choice&&(this.mentions.push(choice),ngModel.$setViewValue(this.replace(choice)),this.cancel(),void ngModel.$render())},this.up=function(){var index=this.choices.indexOf(this.activeChoice);index>0?this.activeChoice=this.choices[index-1]:this.activeChoice=this.choices[this.choices.length-1]},this.down=function(){var index=this.choices.indexOf(this.activeChoice);index<this.choices.length-1?this.activeChoice=this.choices[index+1]:this.activeChoice=this.choices[0]},this.search=function(match){var _this3=this;return this.searching=match,$q.when(this.findChoices(match,this.mentions)).then(function(choices){return _this3.choices=choices,_this3.activeChoice=choices[0],choices})},this.findChoices=function(match,mentions){return[]},this.cancel=function(){this.choices=[],this.searching=null},this.autogrow=function(){$element[0].style.height=0;var style=getComputedStyle($element[0]);"border-box"==style.boxSizing&&($element[0].style.height=$element[0].scrollHeight+"px")},$element.on("keyup click focus",function(event){if(_this2.moved)return _this2.moved=!1;if($element[0].selectionStart==$element[0].selectionEnd){var text=$element.val(),match=_this2.searchPattern.exec(text.substr(0,$element[0].selectionStart));match?_this2.search(match):_this2.cancel(),$scope.$$phase||$scope.$apply()}}),$element.on("keydown",function(event){if(_this2.searching){switch(event.keyCode){case 13:_this2.select();break;case 38:_this2.up();break;case 40:_this2.down();break;default:return}_this2.moved=!0,event.preventDefault(),$scope.$$phase||$scope.$apply()}}),this.onMouseup=function(event){var _this4=this;event.target!=$element[0]&&($document.off("mouseup",this.onMouseup),this.searching&&$scope.$evalAsync(function(){_this4.cancel()}))}.bind(this),$element.on("focus",function(event){$document.on("mouseup",_this2.onMouseup)}),$element.on("input",this.autogrow),$timeout(this.autogrow,!0)}]);