डेमो
मैंने एक ऐसा कार्य लिखा है जो अपेक्षित व्यवहार करता है। यहां एक बहुत विस्तृत प्रदर्शन पैनल पाया जा सकता है: फिडल: http://jsfiddle.net/56Rep/5/
डेमो में इंटरफ़ेस आत्म-व्याख्यात्मक है।
प्रश्न में अनुरोध के रूप में मेरे समारोह में लागू किया जाएगा इस प्रकार है कार्यक्षमता:
var pixelPosition = getTextBoundingRect(input, 6)
समारोह निर्भरता
अपडेट किया गया: समारोह शुद्ध जावास्क्रिप्ट, और किसी भी पर निर्भर नहीं है प्लगइन या ढांचे!
फ़ंक्शन मानता है कि getBoundingClientRect
विधि मौजूद है। पाठ श्रेणियों का उपयोग तब किया जाता है जब वे समर्थित होते हैं। अन्यथा, कार्यक्षमता मेरे फ़ंक्शन तर्क का उपयोग करके हासिल की जाती है।
समारोह तर्क
कोड में ही कई टिप्पणियां हैं। यह हिस्सा एक गहन विस्तार से चला जाता है।
- एक अस्थायी
<div>
कंटेनर बनाया जाता है।
- 1 - 3
<span>
तत्व बनाए गए हैं। प्रत्येक अवधि में इनपुट के मान का एक हिस्सा होता है (ऑफसेट 0 से selectionStart
, selectionStart
selectionEnd
, selectionEnd
स्ट्रिंग के अंत तक, केवल दूसरा अवधि औसत होता है)।
- इनपुट तत्व से कई महत्वपूर्ण शैली गुणों को इन
<div>
और <span>
टैग पर कॉपी किया गया है। केवल महत्वपूर्ण शैली गुणों की प्रतिलिपि बनाई गई है। उदाहरण के लिए, color
कॉपी नहीं किया गया है, क्योंकि यह किसी भी तरह के चरित्र के ऑफसेट को प्रभावित नहीं करता है। # 1
<div>
टेक्स्ट नोड (इनपुट का मूल्य) की सटीक स्थिति पर स्थित है। सीमाओं और पैडिंग को ध्यान में रखा जाता है, यह सुनिश्चित करने के लिए कि अस्थायी <div>
सही स्थित है।
- एक चर बनाया गया है, जिसमें
div.getBoundingClientRect()
का वापसी मूल्य है।
- अस्थायी
<div>
हटा दिया गया है, जब तक पैरामीटर debug
सत्य पर सेट है।
- फ़ंक्शन
ClientRect
ऑब्जेक्ट देता है। इस ऑब्जेक्ट के बारे में अधिक जानकारी के लिए, this page देखें। top
, left
, right
, bottom
, height
और width
: demo भी संपत्तियों की एक सूची दिखाता है।
# 1: getBoundingClientRect()
(और कुछ मामूली गुण) इनपुट तत्व की स्थिति को निर्धारित करने के लिए प्रयोग किया जाता है। फिर, पाठ नोड की वास्तविक स्थिति प्राप्त करने के लिए, पैडिंग और सीमा चौड़ाई जोड़ दी जाती है।
ज्ञात मुद्दे
असंगतता होने की केवल मामले का सामना करना पड़ा था, जब getComputedStyle
font-family
के लिए एक गलत मान दिया: एक पृष्ठ पर एक font-family
संपत्ति परिभाषित नहीं गया है, computedStyle कोई गलत मान देता है (यहां तक कि Firebug इस सामना कर रहा है मुद्दा; पर्यावरण: लिनक्स, फ़ायरफ़ॉक्स 3.6.23, फ़ॉन्ट "सैन्स सेरिफ़")।
डेमो में दिखाई देने के रूप में, स्थिति कभी-कभी थोड़ी दूर होती है (लगभग शून्य, हमेशा 1 पिक्सेल से छोटी)।
तकनीकी प्रतिबंधों को स्क्रिप्ट को स्थानांतरित होने पर स्क्रिप्ट को टेक्स्ट खंड के सटीक ऑफसेट होने से रोकता है, उदाहरण के लिए जब इनपुट फ़ील्ड में पहला दृश्यमान वर्ण पहले मान के वर्ण के बराबर नहीं होता है।
कोड
// @author Rob W http://stackoverflow.com/users/938089/rob-w
// @name getTextBoundingRect
// @param input Required HTMLElement with `value` attribute
// @param selectionStart Optional number: Start offset. Default 0
// @param selectionEnd Optional number: End offset. Default selectionStart
// @param debug Optional boolean. If true, the created test layer
// will not be removed.
function getTextBoundingRect(input, selectionStart, selectionEnd, debug) {
// Basic parameter validation
if(!input || !('value' in input)) return input;
if(typeof selectionStart == "string") selectionStart = parseFloat(selectionStart);
if(typeof selectionStart != "number" || isNaN(selectionStart)) {
selectionStart = 0;
}
if(selectionStart < 0) selectionStart = 0;
else selectionStart = Math.min(input.value.length, selectionStart);
if(typeof selectionEnd == "string") selectionEnd = parseFloat(selectionEnd);
if(typeof selectionEnd != "number" || isNaN(selectionEnd) || selectionEnd < selectionStart) {
selectionEnd = selectionStart;
}
if (selectionEnd < 0) selectionEnd = 0;
else selectionEnd = Math.min(input.value.length, selectionEnd);
// If available (thus IE), use the createTextRange method
if (typeof input.createTextRange == "function") {
var range = input.createTextRange();
range.collapse(true);
range.moveStart('character', selectionStart);
range.moveEnd('character', selectionEnd - selectionStart);
return range.getBoundingClientRect();
}
// createTextRange is not supported, create a fake text range
var offset = getInputOffset(),
topPos = offset.top,
leftPos = offset.left,
width = getInputCSS('width', true),
height = getInputCSS('height', true);
// Styles to simulate a node in an input field
var cssDefaultStyles = "white-space:pre;padding:0;margin:0;",
listOfModifiers = ['direction', 'font-family', 'font-size', 'font-size-adjust', 'font-variant', 'font-weight', 'font-style', 'letter-spacing', 'line-height', 'text-align', 'text-indent', 'text-transform', 'word-wrap', 'word-spacing'];
topPos += getInputCSS('padding-top', true);
topPos += getInputCSS('border-top-width', true);
leftPos += getInputCSS('padding-left', true);
leftPos += getInputCSS('border-left-width', true);
leftPos += 1; //Seems to be necessary
for (var i=0; i<listOfModifiers.length; i++) {
var property = listOfModifiers[i];
cssDefaultStyles += property + ':' + getInputCSS(property) +';';
}
// End of CSS variable checks
var text = input.value,
textLen = text.length,
fakeClone = document.createElement("div");
if(selectionStart > 0) appendPart(0, selectionStart);
var fakeRange = appendPart(selectionStart, selectionEnd);
if(textLen > selectionEnd) appendPart(selectionEnd, textLen);
// Styles to inherit the font styles of the element
fakeClone.style.cssText = cssDefaultStyles;
// Styles to position the text node at the desired position
fakeClone.style.position = "absolute";
fakeClone.style.top = topPos + "px";
fakeClone.style.left = leftPos + "px";
fakeClone.style.width = width + "px";
fakeClone.style.height = height + "px";
document.body.appendChild(fakeClone);
var returnValue = fakeRange.getBoundingClientRect(); //Get rect
if (!debug) fakeClone.parentNode.removeChild(fakeClone); //Remove temp
return returnValue;
// Local functions for readability of the previous code
function appendPart(start, end){
var span = document.createElement("span");
span.style.cssText = cssDefaultStyles; //Force styles to prevent unexpected results
span.textContent = text.substring(start, end);
fakeClone.appendChild(span);
return span;
}
// Computing offset position
function getInputOffset(){
var body = document.body,
win = document.defaultView,
docElem = document.documentElement,
box = document.createElement('div');
box.style.paddingLeft = box.style.width = "1px";
body.appendChild(box);
var isBoxModel = box.offsetWidth == 2;
body.removeChild(box);
box = input.getBoundingClientRect();
var clientTop = docElem.clientTop || body.clientTop || 0,
clientLeft = docElem.clientLeft || body.clientLeft || 0,
scrollTop = win.pageYOffset || isBoxModel && docElem.scrollTop || body.scrollTop,
scrollLeft = win.pageXOffset || isBoxModel && docElem.scrollLeft || body.scrollLeft;
return {
top : box.top + scrollTop - clientTop,
left: box.left + scrollLeft - clientLeft};
}
function getInputCSS(prop, isnumber){
var val = document.defaultView.getComputedStyle(input, null).getPropertyValue(prop);
return isnumber ? parseFloat(val) : val;
}
}
आपकी तलाश के अनुसार हो सकता है: http: // stackoverflow।कॉम/प्रश्न/4085312/jquery-get-the-कर्सर-स्थिति-का-पाठ-इन-इनपुट-बिना ब्राउज़र-विशिष्ट-कोड – Jesse
मुझे पूरा यकीन है कि संक्षिप्त उत्तर "नहीं" है, लेकिन मेरे पास नहीं है अभी विस्तृत करने या शोध करने का समय मिला है। –
@ टिमडाउन मैंने अनुरोधित व्यवहार को लागू किया है। चूंकि आपको श्रेणियों के साथ बहुत अनुभव मिला है (आपकी रंगी परियोजना के कारण), क्या आप इसे देख सकते हैं? –