123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- /*
- 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 内的插入符
- 只实现了获得插入符在文本框中的位置,我设置
- 插入符的位置.
- */
- (function() {
- (function(factory) {
- if (typeof define === 'function' && define.amd) {
- return define(['jquery'], factory);
- } else {
- return factory(window.jQuery);
- }
- })(function($) {
- "use strict";
- var Caret, Mirror, methods, pluginName;
- pluginName = 'caret';
- Caret = (function() {
- function Caret($inputor) {
- this.$inputor = $inputor;
- this.domInputor = this.$inputor[0];
- }
- Caret.prototype.getPos = function() {
- var end, endRange, inputor, len, normalizedValue, pos, range, start, textInputRange;
- inputor = this.domInputor;
- inputor.focus();
- if (document.selection) {
- /*
- #assume we select "HATE" in the inputor such as textarea -> { }.
- * start end-point.
- * /
- * < I really [HATE] IE > between the brackets is the selection range.
- * \
- * end end-point.
- */
- range = document.selection.createRange();
- pos = 0;
- if (range && range.parentElement() === inputor) {
- normalizedValue = inputor.value.replace(/\r\n/g, "\n");
- /* SOMETIME !!!
- "/r/n" is counted as two char.
- one line is two, two will be four. balalala.
- so we have to using the normalized one's length.;
- */
- len = normalizedValue.length;
- /*
- <[ I really HATE IE ]>:
- the whole content in the inputor will be the textInputRange.
- */
- textInputRange = inputor.createTextRange();
- /* _here must be the position of bookmark.
- /
- <[ I really [HATE] IE ]>
- [---------->[ ] : this is what moveToBookmark do.
- < I really [[HATE] IE ]> : here is result.
- \ two brackets in should be in line.
- */
- textInputRange.moveToBookmark(range.getBookmark());
- endRange = inputor.createTextRange();
- /* [--------------------->[] : if set false all end-point goto end.
- < I really [[HATE] IE []]>
- */
- endRange.collapse(false);
- /*
- ___VS____
- / \
- < I really [[HATE] IE []]>
- \_endRange end-point.
-
- " > -1" mean the start end-point will be the same or right to the end end-point
- * simplelly, all in the end.
- */
- if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
- start = end = len;
- } else {
- /*
- I really |HATE] IE ]>
- <-|
- I really[ [HATE] IE ]>
- <-[
- I reall[y [HATE] IE ]>
-
- will return how many unit have moved.
- */
- start = -textInputRange.moveStart("character", -len);
- end = -textInputRange.moveEnd("character", -len);
- }
- }
- } else {
- start = inputor.selectionStart;
- }
- return start;
- };
- Caret.prototype.setPos = function(pos) {
- var inputor, range;
- inputor = this.domInputor;
- if (document.selection) {
- range = inputor.createTextRange();
- range.move("character", pos);
- return range.select();
- } else {
- return inputor.setSelectionRange(pos, pos);
- }
- };
- Caret.prototype.getPosition = function(pos) {
- var $inputor, at_rect, format, h, html, mirror, start_range, x, y;
- $inputor = this.$inputor;
- format = function(value) {
- return value.replace(/</g, '<').replace(/>/g, '>').replace(/`/g, '`').replace(/"/g, '"').replace(/\r\n|\r|\n/g, "<br />");
- };
- pos = pos || this.getPos();
- start_range = $inputor.val().slice(0, pos);
- html = "<span>" + format(start_range) + "</span>";
- html += "<span id='caret'>|</span>";
- mirror = new Mirror($inputor);
- at_rect = mirror.create(html).rect();
- x = at_rect.left - $inputor.scrollLeft();
- y = at_rect.top - $inputor.scrollTop();
- h = at_rect.height;
- return {
- left: x,
- top: y,
- height: h
- };
- };
- Caret.prototype.getOffset = function(pos) {
- var $inputor, h, offset, position, range, x, y;
- $inputor = this.$inputor;
- if (document.selection) {
- range = this.domInputor.createTextRange();
- if (pos) {
- range.move('character', pos);
- }
- x = range.boundingLeft + $inputor.scrollLeft();
- y = range.boundingTop + $(window).scrollTop() + $inputor.scrollTop();
- h = range.boundingHeight;
- } else {
- offset = $inputor.offset();
- position = this.getPosition(pos);
- x = offset.left + position.left;
- y = offset.top + position.top;
- h = position.height;
- }
- return {
- left: x,
- top: y,
- height: h
- };
- };
- return Caret;
- })();
- Mirror = (function() {
- Mirror.prototype.css_attr = ["overflowY", "height", "width", "paddingTop", "paddingLeft", "paddingRight", "paddingBottom", "marginTop", "marginLeft", "marginRight", "marginBottom", "fontFamily", "borderStyle", "borderWidth", "wordWrap", "fontSize", "lineHeight", "overflowX", "text-align"];
- function Mirror($inputor) {
- this.$inputor = $inputor;
- }
- Mirror.prototype.mirrorCss = function() {
- var css,
- _this = this;
- css = {
- position: 'absolute',
- left: -9999,
- top: 0,
- zIndex: -20000,
- 'white-space': 'pre-wrap'
- };
- $.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;
- })();
- methods = {
- pos: function(pos) {
- if (pos) {
- return this.setPos(pos);
- } else {
- return this.getPos();
- }
- },
- position: function(pos) {
- return this.getPosition(pos);
- },
- offset: function(pos) {
- return this.getOffset(pos);
- }
- };
- return $.fn.caret = function(method) {
- var caret;
- caret = new Caret(this);
- if (methods[method]) {
- return methods[method].apply(caret, Array.prototype.slice.call(arguments, 1));
- } else {
- return $.error("Method " + method + " does not exist on jQuery.caret");
- }
- };
- });
- }).call(this);
|