Needed for text modules.
This commit is contained in:
parent
a153681ea1
commit
ea3e365b5e
1 changed files with 367 additions and 0 deletions
367
app/assets/javascripts/app/lib/base/jquery.caret.js
Normal file
367
app/assets/javascripts/app/lib/base/jquery.caret.js
Normal file
|
@ -0,0 +1,367 @@
|
|||
//@ sourceMappingURL=jquery.caret.map
|
||||
/*
|
||||
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 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;
|
||||
if (oWindow.getSelection && (range = this.range())) {
|
||||
if (range.endOffset - 1 < 0) {
|
||||
return null;
|
||||
}
|
||||
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();
|
||||
} 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) {
|
||||
return $('<div></div>').text(value).html().replace(/\r\n|\r|\n/g, "<br/>").replace(/\s/g, " ");
|
||||
};
|
||||
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;
|
||||
return $.fn.caret.apis = methods;
|
||||
});
|
||||
|
||||
}).call(this);
|
Loading…
Reference in a new issue