如何使用 JavaScript 查找 INPUT 和 TEXTAREA 插入符位置坐标?
How To Find INPUT And TEXTAREA Caret Position Coordinates Using JavaScript?
我试图在 type="text"[= 的 TextArea
或 Input
中找出相对于文档(整个网页)的插入符位置坐标38=] 在 JavaScript HTML DOM Events 上的功能类似于 onkeydown
、onkeypress
、onkeyup
等...
为此,我创建了以下 HTML...
<input dir="rtl" type="text" id="TEST_INPUT" onkeydown="myFunction(this)"></input>
<textarea dir="rtl" id="TEST_TEXTAREA" onkeyup="myFunction(this)"></textarea>
和运行以下JavaScript...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coords = getSelectionCoords(Desired_ID);
alert(coords.left + ", " + coords.top);
// Extra Codes Here ETC...
}
/* Get Caret XY Coordinate
----------------------------------------------- */
function getSelectionCoords(Desired_ELEMENT) {
// ------>>> What To Do Here Is The Problem To Cover All Browsers <<<------
return {left:x,top:y};
}
</script>
我在 Whosebug 中搜索并找到了很多,但每个人在使用或 运行 时都遇到了一些问题,这些问题在下面分享...
我的工作 DEMO 在 https://jsfiddle.net/qjkkqdg2/,我正在锻炼,所以你可以分享任何提示或想法来完成它...???
在不断努力和尝试之后,我找到了我想要的答案,我在下面以代码的形式分享它,您也可以在 https://jsfiddle.net/qjkkqdg2/1/ 看到...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coordinates = getCaretCoordinates(Desired_ID, Desired_ID.selectionStart);
alert(coordinates.left + ", " + coordinates.top);
// Extra Codes Here ETC...
}
/* Get Caret XY Coordinate
----------------------------------------------- */
/* jshint browser: true */
(function () {
// The properties that we copy into a mirrored div.
// Note that some browsers, such as Firefox,
// do not concatenate properties, i.e. padding-top, bottom etc. -> padding,
// so we have to do every single property specifically.
var properties = [
'direction', // RTL support
'boxSizing',
'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does
'height',
'overflowX',
'overflowY', // copy the scrollbar for IE
'borderTopWidth',
'borderRightWidth',
'borderBottomWidth',
'borderLeftWidth',
'borderStyle',
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
// https://developer.mozilla.org/en-US/docs/Web/CSS/font
'fontStyle',
'fontVariant',
'fontWeight',
'fontStretch',
'fontSize',
'fontSizeAdjust',
'lineHeight',
'fontFamily',
'textAlign',
'textTransform',
'textIndent',
'textDecoration', // might not make a difference, but better be safe
'letterSpacing',
'wordSpacing',
'tabSize',
'MozTabSize'
];
var isBrowser = (typeof window !== 'undefined');
var isFirefox = (isBrowser && window.mozInnerScreenX != null);
function getCaretCoordinates(element, position, options) {
if(!isBrowser) {
throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser');
}
var debug = options && options.debug || false;
if (debug) {
var el = document.querySelector('#input-textarea-caret-position-mirror-div');
if ( el ) { el.parentNode.removeChild(el); }
}
// mirrored div
var div = document.createElement('div');
div.id = 'input-textarea-caret-position-mirror-div';
document.body.appendChild(div);
var style = div.style;
var computed = window.getComputedStyle? getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9
// default textarea styles
style.whiteSpace = 'pre-wrap';
if (element.nodeName !== 'INPUT')
style.wordWrap = 'break-word'; // only for textarea-s
// position off-screen
style.position = 'absolute'; // required to return coordinates properly
if (!debug)
style.visibility = 'hidden'; // not 'display: none' because we want rendering
// transfer the element's properties to the div
properties.forEach(function (prop) {
style[prop] = computed[prop];
});
if (isFirefox) {
// Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275
if (element.scrollHeight > parseInt(computed.height))
style.overflowY = 'scroll';
} else {
style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'
}
div.textContent = element.value.substring(0, position);
// the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces -
if (element.nodeName === 'INPUT')
div.textContent = div.textContent.replace(/\s/g, '\u00a0');
var span = document.createElement('span');
// Wrapping must be replicated *exactly*, including when a long word gets
// onto the next line, with whitespace at the end of the line before (#7).
// The *only* reliable way to do that is to copy the *entire* rest of the
// textarea's content into the <span> created at the caret position.
// for inputs, just '.' would be enough, but why bother?
span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all
div.appendChild(span);
var coordinates = {
top: span.offsetTop + parseInt(computed['borderTopWidth']),
left: span.offsetLeft + parseInt(computed['borderLeftWidth'])
};
if (debug) {
span.style.backgroundColor = '#aaa';
} else {
document.body.removeChild(div);
}
return coordinates;
}
if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
module.exports = getCaretCoordinates;
} else if(isBrowser){
window.getCaretCoordinates = getCaretCoordinates;
}
}());
</script>
而这个id的代码是https://github.com/component/textarea-caret-position。感谢他...
限制:
它只给出了关于元素的坐标,但我想得到关于整个文档的坐标...
为了解决这个限制,我添加了另一个函数来找出元素相对于整个文档的坐标,所以只需添加下面的函数...
<script type="text/javascript">
/* Get Element XY Coordinate
----------------------------------------------- */
function getElementCoords(elem) { // crossbrowser version
var box = elem.getBoundingClientRect();
var body = document.body;
var docEl = document.documentElement;
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
}
</script>
所以我们的 Main 函数最终会变成...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coordinates = getCaretCoordinates(Desired_ID, Desired_ID.selectionStart);
var elementCoordinates = getElementCoords(Desired_ID);
var topPosition = coordinates.top + elementCoordinates.top;
var leftPosition = coordinates.left + elementCoordinates.left;
alert(leftPosition + ", " + topPosition);
// Extra Codes Here ETC...
}
</script>
所以我们最后一个演示是在 https://jsfiddle.net/qjkkqdg2/2/
我试图在 type="text"[= 的 TextArea
或 Input
中找出相对于文档(整个网页)的插入符位置坐标38=] 在 JavaScript HTML DOM Events 上的功能类似于 onkeydown
、onkeypress
、onkeyup
等...
为此,我创建了以下 HTML...
<input dir="rtl" type="text" id="TEST_INPUT" onkeydown="myFunction(this)"></input>
<textarea dir="rtl" id="TEST_TEXTAREA" onkeyup="myFunction(this)"></textarea>
和运行以下JavaScript...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coords = getSelectionCoords(Desired_ID);
alert(coords.left + ", " + coords.top);
// Extra Codes Here ETC...
}
/* Get Caret XY Coordinate
----------------------------------------------- */
function getSelectionCoords(Desired_ELEMENT) {
// ------>>> What To Do Here Is The Problem To Cover All Browsers <<<------
return {left:x,top:y};
}
</script>
我在 Whosebug 中搜索并找到了很多,但每个人在使用或 运行 时都遇到了一些问题,这些问题在下面分享...
我的工作 DEMO 在 https://jsfiddle.net/qjkkqdg2/,我正在锻炼,所以你可以分享任何提示或想法来完成它...???
在不断努力和尝试之后,我找到了我想要的答案,我在下面以代码的形式分享它,您也可以在 https://jsfiddle.net/qjkkqdg2/1/ 看到...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coordinates = getCaretCoordinates(Desired_ID, Desired_ID.selectionStart);
alert(coordinates.left + ", " + coordinates.top);
// Extra Codes Here ETC...
}
/* Get Caret XY Coordinate
----------------------------------------------- */
/* jshint browser: true */
(function () {
// The properties that we copy into a mirrored div.
// Note that some browsers, such as Firefox,
// do not concatenate properties, i.e. padding-top, bottom etc. -> padding,
// so we have to do every single property specifically.
var properties = [
'direction', // RTL support
'boxSizing',
'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does
'height',
'overflowX',
'overflowY', // copy the scrollbar for IE
'borderTopWidth',
'borderRightWidth',
'borderBottomWidth',
'borderLeftWidth',
'borderStyle',
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
// https://developer.mozilla.org/en-US/docs/Web/CSS/font
'fontStyle',
'fontVariant',
'fontWeight',
'fontStretch',
'fontSize',
'fontSizeAdjust',
'lineHeight',
'fontFamily',
'textAlign',
'textTransform',
'textIndent',
'textDecoration', // might not make a difference, but better be safe
'letterSpacing',
'wordSpacing',
'tabSize',
'MozTabSize'
];
var isBrowser = (typeof window !== 'undefined');
var isFirefox = (isBrowser && window.mozInnerScreenX != null);
function getCaretCoordinates(element, position, options) {
if(!isBrowser) {
throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser');
}
var debug = options && options.debug || false;
if (debug) {
var el = document.querySelector('#input-textarea-caret-position-mirror-div');
if ( el ) { el.parentNode.removeChild(el); }
}
// mirrored div
var div = document.createElement('div');
div.id = 'input-textarea-caret-position-mirror-div';
document.body.appendChild(div);
var style = div.style;
var computed = window.getComputedStyle? getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9
// default textarea styles
style.whiteSpace = 'pre-wrap';
if (element.nodeName !== 'INPUT')
style.wordWrap = 'break-word'; // only for textarea-s
// position off-screen
style.position = 'absolute'; // required to return coordinates properly
if (!debug)
style.visibility = 'hidden'; // not 'display: none' because we want rendering
// transfer the element's properties to the div
properties.forEach(function (prop) {
style[prop] = computed[prop];
});
if (isFirefox) {
// Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275
if (element.scrollHeight > parseInt(computed.height))
style.overflowY = 'scroll';
} else {
style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'
}
div.textContent = element.value.substring(0, position);
// the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces -
if (element.nodeName === 'INPUT')
div.textContent = div.textContent.replace(/\s/g, '\u00a0');
var span = document.createElement('span');
// Wrapping must be replicated *exactly*, including when a long word gets
// onto the next line, with whitespace at the end of the line before (#7).
// The *only* reliable way to do that is to copy the *entire* rest of the
// textarea's content into the <span> created at the caret position.
// for inputs, just '.' would be enough, but why bother?
span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all
div.appendChild(span);
var coordinates = {
top: span.offsetTop + parseInt(computed['borderTopWidth']),
left: span.offsetLeft + parseInt(computed['borderLeftWidth'])
};
if (debug) {
span.style.backgroundColor = '#aaa';
} else {
document.body.removeChild(div);
}
return coordinates;
}
if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
module.exports = getCaretCoordinates;
} else if(isBrowser){
window.getCaretCoordinates = getCaretCoordinates;
}
}());
</script>
而这个id的代码是https://github.com/component/textarea-caret-position。感谢他...
限制:
它只给出了关于元素的坐标,但我想得到关于整个文档的坐标...
为了解决这个限制,我添加了另一个函数来找出元素相对于整个文档的坐标,所以只需添加下面的函数...
<script type="text/javascript">
/* Get Element XY Coordinate
----------------------------------------------- */
function getElementCoords(elem) { // crossbrowser version
var box = elem.getBoundingClientRect();
var body = document.body;
var docEl = document.documentElement;
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
}
</script>
所以我们的 Main 函数最终会变成...
<script type="text/javascript">
/* Main Function
----------------------------------------------- */
function myFunction(Desired_ID){
// Extra Codes Here ETC...
document.getElementById(Desired_ID.id).style.backgroundColor = "red";
// Extra Codes Here ETC...
var coordinates = getCaretCoordinates(Desired_ID, Desired_ID.selectionStart);
var elementCoordinates = getElementCoords(Desired_ID);
var topPosition = coordinates.top + elementCoordinates.top;
var leftPosition = coordinates.left + elementCoordinates.left;
alert(leftPosition + ", " + topPosition);
// Extra Codes Here ETC...
}
</script>
所以我们最后一个演示是在 https://jsfiddle.net/qjkkqdg2/2/