text: /**
   * at.js - 1.5.1
   * Copyright (c) 2016 chord.luo <chord.luo@gmail.com>;
   * Homepage: http://ichord.github.com/At.js
   * License: MIT
   */
  (function (root, factory) {
    if (typeof define === 'function' && define.amd) {
      // AMD. Register as an anonymous module unless amdModuleId is set
      define(["jquery"], function (a0) {
        return (factory(a0));
      });
    } else if (typeof exports === 'object') {
      // Node. Does not work with strict CommonJS, but
      // only CommonJS-like environments that support module.exports,
      // like Node.
      module.exports = factory(require("jquery"));
    } else {
      factory(jQuery);
    }
  }(this, function ($) {
  var DEFAULT_CALLBACKS, KEY_CODE;
  
  KEY_CODE = {
    ESC: 27,
    TAB: 9,
    ENTER: 13,
    CTRL: 17,
    A: 65,
    P: 80,
    N: 78,
    LEFT: 37,
    UP: 38,
    RIGHT: 39,
    DOWN: 40,
    BACKSPACE: 8,
    SPACE: 32
  };
  
  DEFAULT_CALLBACKS = {
    beforeSave: function(data) {
      return Controller.arrayToDefaultHash(data);
    },
    matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) {
      var _a, _y, match, regexp, space;
      flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
      if (should_startWithSpace) {
        flag = '(?:^|\\s)' + flag;
      }
      _a = decodeURI("%C3%80");
      _y = decodeURI("%C3%BF");
      space = acceptSpaceBar ? "\ " : "";
      regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi');
      match = regexp.exec(subtext);
      if (match) {
        return match[2] || match[1];
      } else {
        return null;
      }
    },
    filter: function(query, data, searchKey) {
      var _results, i, item, len;
      _results = [];
      for (i = 0, len = data.length; i < len; i++) {
        item = data[i];
        if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) {
          _results.push(item);
        }
      }
      return _results;
    },
    remoteFilter: null,
    sorter: function(query, items, searchKey) {
      var _results, i, item, len;
      if (!query) {
        return items;
      }
      _results = [];
      for (i = 0, len = items.length; i < len; i++) {
        item = items[i];
        item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase());
        if (item.atwho_order > -1) {
          _results.push(item);
        }
      }
      return _results.sort(function(a, b) {
        return a.atwho_order - b.atwho_order;
      });
    },
    tplEval: function(tpl, map) {
      var error, template;
      template = tpl;
      try {
        if (typeof tpl !== 'string') {
          template = tpl(map);
        }
        return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
          return map[key];
        });
      } catch (error1) {
        error = error1;
        return "";
      }
    },
    highlighter: function(li, query) {
      var regexp;
      if (!query) {
        return li;
      }
      regexp = new RegExp(">\\s*([^\<]*?)(" + query.replace("+", "\\+") + ")([^\<]*)\\s*<", 'ig');
      return li.replace(regexp, function(str, $1, $2, $3) {
        return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
      });
    },
    beforeInsert: function(value, $li, e) {
      return value;
    },
    beforeReposition: function(offset) {
      return offset;
    },
    afterMatchFailed: function(at, el) {}
  };
  
  var App;
  
  App = (function() {
    function App(inputor) {
      this.currentFlag = null;
      this.controllers = {};
      this.aliasMaps = {};
      this.$inputor = $(inputor);
      this.setupRootElement();
      this.listen();
    }
  
    App.prototype.createContainer = function(doc) {
      var ref;
      if ((ref = this.$el) != null) {
        ref.remove();
      }
      return $(doc.body).append(this.$el = $("<div class='atwho-container'></div>"));
    };
  
    App.prototype.setupRootElement = function(iframe, asRoot) {
      var error;
      if (asRoot == null) {
        asRoot = false;
      }
      if (iframe) {
        this.window = iframe.contentWindow;
        this.document = iframe.contentDocument || this.window.document;
        this.iframe = iframe;
      } else {
        this.document = this.$inputor[0].ownerDocument;
        this.window = this.document.defaultView || this.document.parentWindow;
        try {
          this.iframe = this.window.frameElement;
        } catch (error1) {
          error = error1;
          this.iframe = null;
          if ($.fn.atwho.debug) {
            throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error);
          }
        }
      }
      return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document);
    };
  
    App.prototype.controller = function(at) {
      var c, current, currentFlag, ref;
      if (this.aliasMaps[at]) {
        current = this.controllers[this.aliasMaps[at]];
      } else {
        ref = this.controllers;
        for (currentFlag in ref) {
          c = ref[currentFlag];
          if (currentFlag === at) {
            current = c;
            break;
          }
        }
      }
      if (current) {
        return current;
      } else {
        return this.controllers[this.currentFlag];
      }
    };
  
    App.prototype.setContextFor = function(at) {
      this.currentFlag = at;
      return this;
    };
  
    App.prototype.reg = function(flag, setting) {
      var base, controller;
      controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag));
      if (setting.alias) {
        this.aliasMaps[setting.alias] = flag;
      }
      controller.init(setting);
      return this;
    };
  
    App.prototype.listen = function() {
      return this.$inputor.on('compositionstart', (function(_this) {
        return function(e) {
          var ref;
          if ((ref = _this.controller()) != null) {
            ref.view.hide();
          }
          _this.isComposing = true;
          return null;
        };
      })(this)).on('compositionend', (function(_this) {
        return function(e) {
          _this.isComposing = false;
          setTimeout(function() {
            return _this.dispatch(e);
          });
          return null;
        };
      })(this)).on('keyup.atwhoInner', (function(_this) {
        return function(e) {
          return _this.onKeyup(e);
        };
      })(this)).on('keydown.atwhoInner', (function(_this) {
        return function(e) {
          return _this.onKeydown(e);
        };
      })(this)).on('blur.atwhoInner', (function(_this) {
        return function(e) {
          var c;
          if (c = _this.controller()) {
            c.expectedQueryCBId = null;
            return c.view.hide(e, c.getOpt("displayTimeout"));
          }
        };
      })(this)).on('click.atwhoInner', (function(_this) {
        return function(e) {
          return _this.dispatch(e);
        };
      })(this)).on('scroll.atwhoInner', (function(_this) {
        return function() {
          var lastScrollTop;
          lastScrollTop = _this.$inputor.scrollTop();
          return function(e) {
            var currentScrollTop, ref;
            currentScrollTop = e.target.scrollTop;
            if (lastScrollTop !== currentScrollTop) {
              if ((ref = _this.controller()) != null) {
                ref.view.hide(e);
              }
            }
            lastScrollTop = currentScrollTop;
            return true;
          };
        };
      })(this)());
    };
  
    App.prototype.shutdown = function() {
      var _, c, ref;
      ref = this.controllers;
      for (_ in ref) {
        c = ref[_];
        c.destroy();
        delete this.controllers[_];
      }
      this.$inputor.off('.atwhoInner');
      return this.$el.remove();
    };
  
    App.prototype.dispatch = function(e) {
      var _, c, ref, results;
      ref = this.controllers;
      results = [];
      for (_ in ref) {
        c = ref[_];
        results.push(c.lookUp(e));
      }
      return results;
    };
  
    App.prototype.onKeyup = function(e) {
      var ref;
      switch (e.keyCode) {
        case KEY_CODE.ESC:
          e.preventDefault();
          if ((ref = this.controller()) != null) {
            ref.view.hide();
          }
          break;
        case KEY_CODE.DOWN:
        case KEY_CODE.UP:
        case KEY_CODE.CTRL:
        case KEY_CODE.ENTER:
          $.noop();
          break;
        case KEY_CODE.P:
        case KEY_CODE.N:
          if (!e.ctrlKey) {
            this.dispatch(e);
          }
          break;
        default:
          this.dispatch(e);
      }
    };
  
    App.prototype.onKeydown = function(e) {
      var ref, view;
      view = (ref = this.controller()) != null ? ref.view : void 0;
      if (!(view && view.visible())) {
        return;
      }
      switch (e.keyCode) {
        case KEY_CODE.ESC:
          e.preventDefault();
          view.hide(e);
          break;
        case KEY_CODE.UP:
          e.preventDefault();
          view.prev();
          break;
        case KEY_CODE.DOWN:
          e.preventDefault();
          view.next();
          break;
        case KEY_CODE.P:
          if (!e.ctrlKey) {
            return;
          }
          e.preventDefault();
          view.prev();
          break;
        case KEY_CODE.N:
          if (!e.ctrlKey) {
            return;
          }
          e.preventDefault();
          view.next();
          break;
        case KEY_CODE.TAB:
        case KEY_CODE.ENTER:
        case KEY_CODE.SPACE:
          if (!view.visible()) {
            return;
          }
          if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) {
            return;
          }
          if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) {
            return;
          }
          if (view.highlighted()) {
            e.preventDefault();
            view.choose(e);
          } else {
            view.hide(e);
          }
          break;
        default:
          $.noop();
      }
    };
  
    return App;
  
  })();
  
  var Controller,
    slice = [].slice;
  
  Controller = (function() {
    Controller.prototype.uid = function() {
      return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime());
    };
  
    function Controller(app, at1) {
      this.app = app;
      this.at = at1;
      this.$inputor = this.app.$inputor;
      this.id = this.$inputor[0].id || this.uid();
      this.expectedQueryCBId = null;
      this.setting = null;
      this.query = null;
      this.pos = 0;
      this.range = null;
      if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) {
        this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
      }
      this.model = new Model(this);
      this.view = new View(this);
    }
  
    Controller.prototype.init = function(setting) {
      this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
      this.view.init();
      return this.model.reload(this.setting.data);
    };
  
    Controller.prototype.destroy = function() {
      this.trigger('beforeDestroy');
      this.model.destroy();
      this.view.destroy();
      return this.$el.remove();
    };
  
    Controller.prototype.callDefault = function() {
      var args, error, funcName;
      funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      try {
        return DEFAULT_CALLBACKS[funcName].apply(this, args);
      } catch (error1) {
        error = error1;
        return $.error(error + " Or maybe At.js doesn't have function " + funcName);
      }
    };
  
    Controller.prototype.trigger = function(name, data) {
      var alias, eventName;
      if (data == null) {
        data = [];
      }
      data.push(this);
      alias = this.getOpt('alias');
      eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho";
      return this.$inputor.trigger(eventName, data);
    };
  
    Controller.prototype.callbacks = function(funcName) {
      return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName];
    };
  
    Controller.prototype.getOpt = function(at, default_value) {
      var e;
      try {
        return this.setting[at];
      } catch (error1) {
        e = error1;
        return null;
      }
    };
  
    Controller.prototype.insertContentFor = function($li) {
      var data, tpl;
      tpl = this.getOpt('insertTpl');
      data = $.extend({}, $li.data('item-data'), {
        'atwho-at': this.at
      });
      return this.callbacks("tplEval").call(this, tpl, data, "onInsert");
    };
  
    Controller.prototype.renderView = function(data) {
      var searchKey;
      searchKey = this.getOpt("searchKey");
      data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey);
      return this.view.render(data.slice(0, this.getOpt('limit')));
    };
  
    Controller.arrayToDefaultHash = function(data) {
      var i, item, len, results;
      if (!$.isArray(data)) {
        return data;
      }
      results = [];
      for (i = 0, len = data.length; i < len; i++) {
        item = data[i];
        if ($.isPlainObject(item)) {
          results.push(item);
        } else {
          results.push({
            name: item
          });
        }
      }
      return results;
    };
  
    Controller.prototype.lookUp = function(e) {
      var query, wait;
      if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) {
        return;
      }
      if (this.getOpt('suspendOnComposing') && this.app.isComposing) {
        return;
      }
      query = this.catchQuery(e);
      if (!query) {
        this.expectedQueryCBId = null;
        return query;
      }
      this.app.setContextFor(this.at);
      if (wait = this.getOpt('delay')) {
        this._delayLookUp(query, wait);
      } else {
        this._lookUp(query);
      }
      return query;
    };
  
    Controller.prototype._delayLookUp = function(query, wait) {
      var now, remaining;
      now = Date.now ? Date.now() : new Date().getTime();
      this.previousCallTime || (this.previousCallTime = now);
      remaining = wait - (now - this.previousCallTime);
      if ((0 < remaining && remaining < wait)) {
        this.previousCallTime = now;
        this._stopDelayedCall();
        return this.delayedCallTimeout = setTimeout((function(_this) {
          return function() {
            _this.previousCallTime = 0;
            _this.delayedCallTimeout = null;
            return _this._lookUp(query);
          };
        })(this), wait);
      } else {
        this._stopDelayedCall();
        if (this.previousCallTime !== now) {
          this.previousCallTime = 0;
        }
        return this._lookUp(query);
      }
    };
  
    Controller.prototype._stopDelayedCall = function() {
      if (this.delayedCallTimeout) {
        clearTimeout(this.delayedCallTimeout);
        return this.delayedCallTimeout = null;
      }
    };
  
    Controller.prototype._generateQueryCBId = function() {
      return {};
    };
  
    Controller.prototype._lookUp = function(query) {
      var _callback;
      _callback = function(queryCBId, data) {
        if (queryCBId !== this.expectedQueryCBId) {
          return;
        }
        if (data && data.length > 0) {
          return this.renderView(this.constructor.arrayToDefaultHash(data));
        } else {
          return this.view.hide();
        }
      };
      this.expectedQueryCBId = this._generateQueryCBId();
      return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId));
    };
  
    return Controller;
  
  })();
  
  var TextareaController,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  TextareaController = (function(superClass) {
    extend(TextareaController, superClass);
  
    function TextareaController() {
      return TextareaController.__super__.constructor.apply(this, arguments);
    }
  
    TextareaController.prototype.catchQuery = function() {
      var caretPos, content, end, isString, query, start, subtext;
      content = this.$inputor.val();
      caretPos = this.$inputor.caret('pos', {
        iframe: this.app.iframe
      });
      subtext = content.slice(0, caretPos);
      query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
      isString = typeof query === 'string';
      if (isString && query.length < this.getOpt('minLen', 0)) {
        return;
      }
      if (isString && query.length <= this.getOpt('maxLen', 20)) {
        start = caretPos - query.length;
        end = start + query.length;
        this.pos = start;
        query = {
          'text': query,
          'headPos': start,
          'endPos': end
        };
        this.trigger("matched", [this.at, query.text]);
      } else {
        query = null;
        this.view.hide();
      }
      return this.query = query;
    };
  
    TextareaController.prototype.rect = function() {
      var c, iframeOffset, scaleBottom;
      if (!(c = this.$inputor.caret('offset', this.pos - 1, {
        iframe: this.app.iframe
      }))) {
        return;
      }
      if (this.app.iframe && !this.app.iframeAsRoot) {
        iframeOffset = $(this.app.iframe).offset();
        c.left += iframeOffset.left;
        c.top += iframeOffset.top;
      }
      scaleBottom = this.app.document.selection ? 0 : 2;
      return {
        left: c.left,
        top: c.top,
        bottom: c.top + c.height + scaleBottom
      };
    };
  
    TextareaController.prototype.insert = function(content, $li) {
      var $inputor, source, startStr, suffix, text;
      $inputor = this.$inputor;
      source = $inputor.val();
      startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0));
      suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " ";
      content += suffix;
      text = "" + startStr + content + (source.slice(this.query['endPos'] || 0));
      $inputor.val(text);
      $inputor.caret('pos', startStr.length + content.length, {
        iframe: this.app.iframe
      });
      if (!$inputor.is(':focus')) {
        $inputor.focus();
      }
      return $inputor.change();
    };
  
    return TextareaController;
  
  })(Controller);
  
  var EditableController,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  EditableController = (function(superClass) {
    extend(EditableController, superClass);
  
    function EditableController() {
      return EditableController.__super__.constructor.apply(this, arguments);
    }
  
    EditableController.prototype._getRange = function() {
      var sel;
      sel = this.app.window.getSelection();
      if (sel.rangeCount > 0) {
        return sel.getRangeAt(0);
      }
    };
  
    EditableController.prototype._setRange = function(position, node, range) {
      if (range == null) {
        range = this._getRange();
      }
      if (!(range && node)) {
        return;
      }
      node = $(node)[0];
      if (position === 'after') {
        range.setEndAfter(node);
        range.setStartAfter(node);
      } else {
        range.setEndBefore(node);
        range.setStartBefore(node);
      }
      range.collapse(false);
      return this._clearRange(range);
    };
  
    EditableController.prototype._clearRange = function(range) {
      var sel;
      if (range == null) {
        range = this._getRange();
      }
      sel = this.app.window.getSelection();
      if (this.ctrl_a_pressed == null) {
        sel.removeAllRanges();
        return sel.addRange(range);
      }
    };
  
    EditableController.prototype._movingEvent = function(e) {
      var ref;
      return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN);
    };
  
    EditableController.prototype._unwrap = function(node) {
      var next;
      node = $(node).unwrap().get(0);
      if ((next = node.nextSibling) && next.nodeValue) {
        node.nodeValue += next.nodeValue;
        $(next).remove();
      }
      return node;
    };
  
    EditableController.prototype.catchQuery = function(e) {
      var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range;
      if (!(range = this._getRange())) {
        return;
      }
      if (!range.collapsed) {
        return;
      }
      if (e.which === KEY_CODE.ENTER) {
        ($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap();
        if ($query.is(':empty')) {
          $query.remove();
        }
        ($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last().unwrap();
        this._clearRange();
        return;
      }
      if (/firefox/i.test(navigator.userAgent)) {
        if ($(range.startContainer).is(this.$inputor)) {
          this._clearRange();
          return;
        }
        if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) {
          _range = range.cloneRange();
          _range.setStart(range.startContainer, offset);
          if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) {
            inserted = $(range.startContainer).contents().get(offset);
            this._setRange('after', $(inserted).contents().last());
          }
        } else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) {
          $inserted = $(range.startContainer.previousSibling);
          if ($inserted.is('.atwho-inserted') && range.startOffset === 0) {
            this._setRange('after', $inserted.contents().last());
          }
        }
      }
      $(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query');
      if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) {
        $query.remove();
      }
      if (!this._movingEvent(e)) {
        $query.removeClass('atwho-inserted');
      }
      if ($query.length > 0) {
        switch (e.which) {
          case KEY_CODE.LEFT:
            this._setRange('before', $query.get(0), range);
            $query.removeClass('atwho-query');
            return;
          case KEY_CODE.RIGHT:
            this._setRange('after', $query.get(0).nextSibling, range);
            $query.removeClass('atwho-query');
            return;
        }
      }
      if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) {
        $query.empty().html(query_content).attr('data-atwho-at-query', null);
        this._setRange('after', $query.get(0), range);
      }
      _range = range.cloneRange();
      _range.setStart(range.startContainer, 0);
      matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
      isString = typeof matched === 'string';
      if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) {
        range.setStart(range.startContainer, index);
        $query = $('<span/>', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query');
        range.surroundContents($query.get(0));
        lastNode = $query.contents().last().get(0);
        if (lastNode) {
          if (/firefox/i.test(navigator.userAgent)) {
            range.setStart(lastNode, lastNode.length);
            range.setEnd(lastNode, lastNode.length);
            this._clearRange(range);
          } else {
            this._setRange('after', lastNode, range);
          }
        }
      }
      if (isString && matched.length < this.getOpt('minLen', 0)) {
        return;
      }
      if (isString && matched.length <= this.getOpt('maxLen', 20)) {
        query = {
          text: matched,
          el: $query
        };
        this.trigger("matched", [this.at, query.text]);
        return this.query = query;
      } else {
        this.view.hide();
        this.query = {
          el: $query
        };
        if ($query.text().indexOf(this.at) >= 0) {
          if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) {
            $query.removeClass('atwho-query');
          } else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) {
            this._setRange("after", this._unwrap($query.text($query.text()).contents().first()));
          }
        }
        return null;
      }
    };
  
    EditableController.prototype.rect = function() {
      var $iframe, iframeOffset, rect;
      rect = this.query.el.offset();
      if (!rect) {
        return;
      }
      if (this.app.iframe && !this.app.iframeAsRoot) {
        iframeOffset = ($iframe = $(this.app.iframe)).offset();
        rect.left += iframeOffset.left - this.$inputor.scrollLeft();
        rect.top += iframeOffset.top - this.$inputor.scrollTop();
      }
      rect.bottom = rect.top + this.query.el.height();
      return rect;
    };
  
    EditableController.prototype.insert = function(content, $li) {
      var data, overrides, range, suffix, suffixNode;
      if (!this.$inputor.is(':focus')) {
        this.$inputor.focus();
      }
      overrides = this.getOpt("functionOverrides");
      if (overrides.insert) {
        return overrides.insert.bind(this)(content, $li);
      } else {
        suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0";
        data = $li.data('item-data');
        this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text).attr('contenteditable', "false");
        if (range = this._getRange()) {
          if (this.query.el.length) {
            range.setEndAfter(this.query.el[0]);
          }
          range.collapse(false);
          range.insertNode(suffixNode = this.app.document.createTextNode("\u200D" + suffix));
          this._setRange('after', suffixNode, range);
        }
        if (!this.$inputor.is(':focus')) {
          this.$inputor.focus();
        }
        return this.$inputor.change();
      }
    };
  
    return EditableController;
  
  })(Controller);
  
  var Model;
  
  Model = (function() {
    function Model(context) {
      this.context = context;
      this.at = this.context.at;
      this.storage = this.context.$inputor;
    }
  
    Model.prototype.destroy = function() {
      return this.storage.data(this.at, null);
    };
  
    Model.prototype.saved = function() {
      return this.fetch() > 0;
    };
  
    Model.prototype.query = function(query, callback) {
      var _remoteFilter, data, searchKey;
      data = this.fetch();
      searchKey = this.context.getOpt("searchKey");
      data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || [];
      _remoteFilter = this.context.callbacks('remoteFilter');
      if (data.length > 0 || (!_remoteFilter && data.length === 0)) {
        return callback(data);
      } else {
        return _remoteFilter.call(this.context, query, callback);
      }
    };
  
    Model.prototype.fetch = function() {
      return this.storage.data(this.at) || [];
    };
  
    Model.prototype.save = function(data) {
      return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || []));
    };
  
    Model.prototype.load = function(data) {
      if (!(this.saved() || !data)) {
        return this._load(data);
      }
    };
  
    Model.prototype.reload = function(data) {
      return this._load(data);
    };
  
    Model.prototype._load = function(data) {
      if (typeof data === "string") {
        return $.ajax(data, {
          dataType: "json"
        }).done((function(_this) {
          return function(data) {
            return _this.save(data);
          };
        })(this));
      } else {
        return this.save(data);
      }
    };
  
    return Model;
  
  })();
  
  var View;
  
  View = (function() {
    function View(context) {
      this.context = context;
      this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
      this.$elUl = this.$el.children();
      this.timeoutID = null;
      this.context.$el.append(this.$el);
      this.bindEvent();
    }
  
    View.prototype.init = function() {
      var header_tpl, id;
      id = this.context.getOpt("alias") || this.context.at.charCodeAt(0);
      header_tpl = this.context.getOpt("headerTpl");
      if (header_tpl && this.$el.children().length === 1) {
        this.$el.prepend(header_tpl);
      }
      return this.$el.attr({
        'id': "at-view-" + id
      });
    };
  
    View.prototype.destroy = function() {
      return this.$el.remove();
    };
  
    View.prototype.bindEvent = function() {
      var $menu, lastCoordX, lastCoordY;
      $menu = this.$el.find('ul');
      lastCoordX = 0;
      lastCoordY = 0;
      return $menu.on('mousemove.atwho-view', 'li', (function(_this) {
        return function(e) {
          var $cur;
          if (lastCoordX === e.clientX && lastCoordY === e.clientY) {
            return;
          }
          lastCoordX = e.clientX;
          lastCoordY = e.clientY;
          $cur = $(e.currentTarget);
          if ($cur.hasClass('cur')) {
            return;
          }
          $menu.find('.cur').removeClass('cur');
          return $cur.addClass('cur');
        };
      })(this)).on('click.atwho-view', 'li', (function(_this) {
        return function(e) {
          $menu.find('.cur').removeClass('cur');
          $(e.currentTarget).addClass('cur');
          _this.choose(e);
          return e.preventDefault();
        };
      })(this));
    };
  
    View.prototype.visible = function() {
      return $.expr.filters.visible(this.$el[0]);
    };
  
    View.prototype.highlighted = function() {
      return this.$el.find(".cur").length > 0;
    };
  
    View.prototype.choose = function(e) {
      var $li, content;
      if (($li = this.$el.find(".cur")).length) {
        content = this.context.insertContentFor($li);
        this.context._stopDelayedCall();
        this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li, e), $li);
        this.context.trigger("inserted", [$li, e]);
        this.hide(e);
      }
      if (this.context.getOpt("hideWithoutSuffix")) {
        return this.stopShowing = true;
      }
    };
  
    View.prototype.reposition = function(rect) {
      var _window, offset, overflowOffset, ref;
      _window = this.context.app.iframeAsRoot ? this.context.app.window : window;
      if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) {
        rect.bottom = rect.top - this.$el.height();
      }
      if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) {
        rect.left = overflowOffset;
      }
      offset = {
        left: rect.left,
        top: rect.bottom
      };
      if ((ref = this.context.callbacks("beforeReposition")) != null) {
        ref.call(this.context, offset);
      }
      this.$el.offset(offset);
      return this.context.trigger("reposition", [offset]);
    };
  
    View.prototype.next = function() {
      var cur, next, nextEl, offset;
      cur = this.$el.find('.cur').removeClass('cur');
      next = cur.next();
      if (!next.length) {
        next = this.$el.find('li:first');
      }
      next.addClass('cur');
      nextEl = next[0];
      offset = nextEl.offsetTop + nextEl.offsetHeight + (nextEl.nextSibling ? nextEl.nextSibling.offsetHeight : 0);
      return this.scrollTop(Math.max(0, offset - this.$el.height()));
    };
  
    View.prototype.prev = function() {
      var cur, offset, prev, prevEl;
      cur = this.$el.find('.cur').removeClass('cur');
      prev = cur.prev();
      if (!prev.length) {
        prev = this.$el.find('li:last');
      }
      prev.addClass('cur');
      prevEl = prev[0];
      offset = prevEl.offsetTop + prevEl.offsetHeight + (prevEl.nextSibling ? prevEl.nextSibling.offsetHeight : 0);
      return this.scrollTop(Math.max(0, offset - this.$el.height()));
    };
  
    View.prototype.scrollTop = function(scrollTop) {
      var scrollDuration;
      scrollDuration = this.context.getOpt('scrollDuration');
      if (scrollDuration) {
        return this.$elUl.animate({
          scrollTop: scrollTop
        }, scrollDuration);
      } else {
        return this.$elUl.scrollTop(scrollTop);
      }
    };
  
    View.prototype.show = function() {
      var rect;
      if (this.stopShowing) {
        this.stopShowing = false;
        return;
      }
      if (!this.visible()) {
        this.$el.show();
        this.$el.scrollTop(0);
        this.context.trigger('shown');
      }
      if (rect = this.context.rect()) {
        return this.reposition(rect);
      }
    };
  
    View.prototype.hide = function(e, time) {
      var callback;
      if (!this.visible()) {
        return;
      }
      if (isNaN(time)) {
        this.$el.hide();
        return this.context.trigger('hidden', [e]);
      } else {
        callback = (function(_this) {
          return function() {
            return _this.hide();
          };
        })(this);
        clearTimeout(this.timeoutID);
        return this.timeoutID = setTimeout(callback, time);
      }
    };
  
    View.prototype.render = function(list) {
      var $li, $ul, i, item, len, li, tpl;
      if (!($.isArray(list) && list.length > 0)) {
        this.hide();
        return;
      }
      this.$el.find('ul').empty();
      $ul = this.$el.find('ul');
      tpl = this.context.getOpt('displayTpl');
      for (i = 0, len = list.length; i < len; i++) {
        item = list[i];
        item = $.extend({}, item, {
          'atwho-at': this.context.at
        });
        li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay");
        $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
        $li.data("item-data", item);
        $ul.append($li);
      }
      this.show();
      if (this.context.getOpt('highlightFirst')) {
        return $ul.find("li:first").addClass("cur");
      }
    };
  
    return View;
  
  })();
  
  var Api;
  
  Api = {
    load: function(at, data) {
      var c;
      if (c = this.controller(at)) {
        return c.model.load(data);
      }
    },
    isSelecting: function() {
      var ref;
      return !!((ref = this.controller()) != null ? ref.view.visible() : void 0);
    },
    hide: function() {
      var ref;
      return (ref = this.controller()) != null ? ref.view.hide() : void 0;
    },
    reposition: function() {
      var c;
      if (c = this.controller()) {
        return c.view.reposition(c.rect());
      }
    },
    setIframe: function(iframe, asRoot) {
      this.setupRootElement(iframe, asRoot);
      return null;
    },
    run: function() {
      return this.dispatch();
    },
    destroy: function() {
      this.shutdown();
      return this.$inputor.data('atwho', null);
    }
  };
  
  $.fn.atwho = function(method) {
    var _args, result;
    _args = arguments;
    result = null;
    this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() {
      var $this, app;
      if (!(app = ($this = $(this)).data("atwho"))) {
        $this.data('atwho', (app = new App(this)));
      }
      if (typeof method === 'object' || !method) {
        return app.reg(method.at, method);
      } else if (Api[method] && app) {
        return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
      } else {
        return $.error("Method " + method + " does not exist on jQuery.atwho");
      }
    });
    if (result != null) {
      return result;
    } else {
      return this;
    }
  };
  
  $.fn.atwho["default"] = {
    at: void 0,
    alias: void 0,
    data: null,
    displayTpl: "<li>${name}</li>",
    insertTpl: "${atwho-at}${name}",
    headerTpl: null,
    callbacks: DEFAULT_CALLBACKS,
    functionOverrides: {},
    searchKey: "name",
    suffix: void 0,
    hideWithoutSuffix: false,
    startWithSpace: true,
    acceptSpaceBar: false,
    highlightFirst: true,
    limit: 5,
    maxLen: 20,
    minLen: 0,
    displayTimeout: 300,
    delay: null,
    spaceSelectsMatch: false,
    tabSelectsMatch: true,
    editableAtwhoQueryAttrs: {},
    scrollDuration: 150,
    suspendOnComposing: true,
    lookUpOnClick: true
  };
  
  $.fn.atwho.debug = false;
  
  }));
  