(function (root, factory) {

if (typeof define === 'function' && define.amd) {
  // AMD. Register as an anonymous module.
  define(["jquery"], function ($) {
    return (root.returnExportsGlobal = factory($));
  });
} else if (typeof exports === 'object') {
  // Node. Does not work with strict CommonJS, but
  // only CommonJS-like enviroments that support module.exports,
  // like Node.
  module.exports = factory(require("jquery"));
} else {
  factory(jQuery);
}

}(this, function ($) {

Implement Github like autocomplete mentions
http://ichord.github.com/At.js

Copyright (c) 2013 chord.luo@gmail.com
Licensed under the MIT license.

/* 本插件操作 textarea 或者 input 内的插入符 只实现了获得插入符在文本框中的位置,我设置 插入符的位置.

/

“use strict”; var EditableCaret, InputCaret, Mirror, Utils, discoveryIframeOf, methods, oDocument, oFrame, oWindow, pluginName, setContextBy;

pluginName = 'caret';

EditableCaret = (function() {

function EditableCaret($inputor) {
  this.$inputor = $inputor;
  this.domInputor = this.$inputor[0];
}

EditableCaret.prototype.setPos = function(pos) {
  return this.domInputor;
};

EditableCaret.prototype.getIEPosition = function() {
  return this.getPosition();
};

EditableCaret.prototype.getPosition = function() {
  var inputor_offset, offset;
  offset = this.getOffset();
  inputor_offset = this.$inputor.offset();
  offset.left -= inputor_offset.left;
  offset.top -= inputor_offset.top;
  return offset;
};

EditableCaret.prototype.getOldIEPos = function() {
  var preCaretTextRange, textRange;
  textRange = oDocument.selection.createRange();
  preCaretTextRange = oDocument.body.createTextRange();
  preCaretTextRange.moveToElementText(this.domInputor);
  preCaretTextRange.setEndPoint("EndToEnd", textRange);
  return preCaretTextRange.text.length;
};

EditableCaret.prototype.getPos = function() {
  var clonedRange, pos, range;
  if (range = this.range()) {
    clonedRange = range.cloneRange();
    clonedRange.selectNodeContents(this.domInputor);
    clonedRange.setEnd(range.endContainer, range.endOffset);
    pos = clonedRange.toString().length;
    clonedRange.detach();
    return pos;
  } else if (oDocument.selection) {
    return this.getOldIEPos();
  }
};

EditableCaret.prototype.getOldIEOffset = function() {
  var range, rect;
  range = oDocument.selection.createRange().duplicate();
  range.moveStart("character", -1);
  rect = range.getBoundingClientRect();
  return {
    height: rect.bottom - rect.top,
    left: rect.left,
    top: rect.top
  };
};

EditableCaret.prototype.getOffset = function(pos) {
  var clonedRange, offset, range, rect, shadowCaret;
  if (oWindow.getSelection && (range = this.range())) {
    if (range.endOffset - 1 > 0 && range.endContainer === !this.domInputor) {
      clonedRange = range.cloneRange();
      clonedRange.setStart(range.endContainer, range.endOffset - 1);
      clonedRange.setEnd(range.endContainer, range.endOffset);
      rect = clonedRange.getBoundingClientRect();
      offset = {
        height: rect.height,
        left: rect.left + rect.width,
        top: rect.top
      };
      clonedRange.detach();
    }
    if (!offset || (offset != null ? offset.height : void 0) === 0) {
      clonedRange = range.cloneRange();
      shadowCaret = $(oDocument.createTextNode("|"));
      clonedRange.insertNode(shadowCaret[0]);
      clonedRange.selectNode(shadowCaret[0]);
      rect = clonedRange.getBoundingClientRect();
      offset = {
        height: rect.height,
        left: rect.left,
        top: rect.top
      };
      shadowCaret.remove();
      clonedRange.detach();
    }
  } else if (oDocument.selection) {
    offset = this.getOldIEOffset();
  }
  if (offset) {
    offset.top += $(oWindow).scrollTop();
    offset.left += $(oWindow).scrollLeft();
  }
  return offset;
};

EditableCaret.prototype.range = function() {
  var sel;
  if (!oWindow.getSelection) {
    return;
  }
  sel = oWindow.getSelection();
  if (sel.rangeCount > 0) {
    return sel.getRangeAt(0);
  } else {
    return null;
  }
};

return EditableCaret;

})();

InputCaret = (function() {

function InputCaret($inputor) {
  this.$inputor = $inputor;
  this.domInputor = this.$inputor[0];
}

InputCaret.prototype.getIEPos = function() {
  var endRange, inputor, len, normalizedValue, pos, range, textInputRange;
  inputor = this.domInputor;
  range = oDocument.selection.createRange();
  pos = 0;
  if (range && range.parentElement() === inputor) {
    normalizedValue = inputor.value.replace(/\r\n/g, "\n");
    len = normalizedValue.length;
    textInputRange = inputor.createTextRange();
    textInputRange.moveToBookmark(range.getBookmark());
    endRange = inputor.createTextRange();
    endRange.collapse(false);
    if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
      pos = len;
    } else {
      pos = -textInputRange.moveStart("character", -len);
    }
  }
  return pos;
};

InputCaret.prototype.getPos = function() {
  if (oDocument.selection) {
    return this.getIEPos();
  } else {
    return this.domInputor.selectionStart;
  }
};

InputCaret.prototype.setPos = function(pos) {
  var inputor, range;
  inputor = this.domInputor;
  if (oDocument.selection) {
    range = inputor.createTextRange();
    range.move("character", pos);
    range.select();
  } else if (inputor.setSelectionRange) {
    inputor.setSelectionRange(pos, pos);
  }
  return inputor;
};

InputCaret.prototype.getIEOffset = function(pos) {
  var h, textRange, x, y;
  textRange = this.domInputor.createTextRange();
  pos || (pos = this.getPos());
  textRange.move('character', pos);
  x = textRange.boundingLeft;
  y = textRange.boundingTop;
  h = textRange.boundingHeight;
  return {
    left: x,
    top: y,
    height: h
  };
};

InputCaret.prototype.getOffset = function(pos) {
  var $inputor, offset, position;
  $inputor = this.$inputor;
  if (oDocument.selection) {
    offset = this.getIEOffset(pos);
    offset.top += $(oWindow).scrollTop() + $inputor.scrollTop();
    offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft();
    return offset;
  } else {
    offset = $inputor.offset();
    position = this.getPosition(pos);
    return offset = {
      left: offset.left + position.left - $inputor.scrollLeft(),
      top: offset.top + position.top - $inputor.scrollTop(),
      height: position.height
    };
  }
};

InputCaret.prototype.getPosition = function(pos) {
  var $inputor, at_rect, end_range, format, html, mirror, start_range;
  $inputor = this.$inputor;
  format = function(value) {
    value = value.replace(/<|>|`|"|&/g, '?').replace(/\r\n|\r|\n/g, "<br/>");
    if (/firefox/i.test(navigator.userAgent)) {
      value = value.replace(/\s/g, '&nbsp;');
    }
    return value;
  };
  if (pos === void 0) {
    pos = this.getPos();
  }
  start_range = $inputor.val().slice(0, pos);
  end_range = $inputor.val().slice(pos);
  html = "<span style='position: relative; display: inline;'>" + format(start_range) + "</span>";
  html += "<span id='caret' style='position: relative; display: inline;'>|</span>";
  html += "<span style='position: relative; display: inline;'>" + format(end_range) + "</span>";
  mirror = new Mirror($inputor);
  return at_rect = mirror.create(html).rect();
};

InputCaret.prototype.getIEPosition = function(pos) {
  var h, inputorOffset, offset, x, y;
  offset = this.getIEOffset(pos);
  inputorOffset = this.$inputor.offset();
  x = offset.left - inputorOffset.left;
  y = offset.top - inputorOffset.top;
  h = offset.height;
  return {
    left: x,
    top: y,
    height: h
  };
};

return InputCaret;

})();

Mirror = (function() {

Mirror.prototype.css_attr = ["borderBottomWidth", "borderLeftWidth", "borderRightWidth", "borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle", "borderTopWidth", "boxSizing", "fontFamily", "fontSize", "fontWeight", "height", "letterSpacing", "lineHeight", "marginBottom", "marginLeft", "marginRight", "marginTop", "outlineWidth", "overflow", "overflowX", "overflowY", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "textAlign", "textOverflow", "textTransform", "whiteSpace", "wordBreak", "wordWrap"];

function Mirror($inputor) {
  this.$inputor = $inputor;
}

Mirror.prototype.mirrorCss = function() {
  var css,
    _this = this;
  css = {
    position: 'absolute',
    left: -9999,
    top: 0,
    zIndex: -20000
  };
  if (this.$inputor.prop('tagName') === 'TEXTAREA') {
    this.css_attr.push('width');
  }
  $.each(this.css_attr, function(i, p) {
    return css[p] = _this.$inputor.css(p);
  });
  return css;
};

Mirror.prototype.create = function(html) {
  this.$mirror = $('<div></div>');
  this.$mirror.css(this.mirrorCss());
  this.$mirror.html(html);
  this.$inputor.after(this.$mirror);
  return this;
};

Mirror.prototype.rect = function() {
  var $flag, pos, rect;
  $flag = this.$mirror.find("#caret");
  pos = $flag.position();
  rect = {
    left: pos.left,
    top: pos.top,
    height: $flag.height()
  };
  this.$mirror.remove();
  return rect;
};

return Mirror;

})();

Utils = {

contentEditable: function($inputor) {
  return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true');
}

};

methods = {

pos: function(pos) {
  if (pos || pos === 0) {
    return this.setPos(pos);
  } else {
    return this.getPos();
  }
},
position: function(pos) {
  if (oDocument.selection) {
    return this.getIEPosition(pos);
  } else {
    return this.getPosition(pos);
  }
},
offset: function(pos) {
  var offset;
  offset = this.getOffset(pos);
  return offset;
}

};

oDocument = null;

oWindow = null;

oFrame = null;

setContextBy = function(settings) {

var iframe;
if (iframe = settings != null ? settings.iframe : void 0) {
  oFrame = iframe;
  oWindow = iframe.contentWindow;
  return oDocument = iframe.contentDocument || oWindow.document;
} else {
  oFrame = void 0;
  oWindow = window;
  return oDocument = document;
}

};

discoveryIframeOf = function($dom) {

var error;
oDocument = $dom[0].ownerDocument;
oWindow = oDocument.defaultView || oDocument.parentWindow;
try {
  return oFrame = oWindow.frameElement;
} catch (_error) {
  error = _error;
}

};

$.fn.caret = function(method, value, settings) {

var caret;
if (methods[method]) {
  if ($.isPlainObject(value)) {
    setContextBy(value);
    value = void 0;
  } else {
    setContextBy(settings);
  }
  caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this);
  return methods[method].apply(caret, [value]);
} else {
  return $.error("Method " + method + " does not exist on jQuery.caret");
}

};

$.fn.caret.EditableCaret = EditableCaret;

$.fn.caret.InputCaret = InputCaret;

$.fn.caret.Utils = Utils;

$.fn.caret.apis = methods;

}));