2015-06-22 4 views
7

मैं एक कस्टम पाठ क्षेत्र है प्रदर्शित किए बिना एक कस्टम पाठ क्षेत्र में एक कैरट दिखाएं। इस उदाहरण में, यह यादृच्छिक रूप से अक्षरों को लाल या हरा बनाता है।अपने पाठ

var mydiv = document.getElementById('mydiv'), 
 
    myta = document.getElementById('myta'); 
 
function updateDiv() { 
 
    var fc; 
 
    while (fc = mydiv.firstChild) mydiv.removeChild(fc); 
 
    for (var i = 0; i < myta.value.length; i++) { 
 
    var span = document.createElement('span'); 
 
    span.className = Math.random() < 0.5 ? 'green' : 'red'; 
 
    span.appendChild(document.createTextNode(myta.value[i])); 
 
    mydiv.appendChild(span); 
 
    } 
 
}; 
 
myta.addEventListener('input', updateDiv);
body { position: relative } 
 
div, textarea { 
 
    -webkit-text-size-adjust: none; 
 
    width: 100%; 
 
    white-space: pre-wrap; 
 
    word-wrap: break-word; 
 
    overflow-wrap: break-word; 
 
    font: 1rem sans-serif; 
 
    padding: 2px; 
 
    margin: 0; 
 
    border-radius: 0; 
 
    border: 1px solid #000; 
 
    resize: none; 
 
} 
 
textarea { 
 
    position: absolute; 
 
    top: 0; 
 
    color: transparent; 
 
    background: transparent; 
 
} 
 
.red { color: #f00 } 
 
.green { color: #0f0 }
<div id="mydiv"></div> 
 
<textarea id="myta" autofocus=""></textarea>

इस पर एक पाठ क्षेत्र के साथ एक निर्गम div नहीं है। तो textarea नीचे रंगीन चीजों को कवर नहीं करता है, इसका रंग और पृष्ठभूमि पारदर्शी पर सेट हैं। सबकुछ यहां काम करता है, सिवाय इसके कि देखभाल (उपयोगकर्ता एजेंट द्वारा प्रदान किया गया चमकदार कर्सर) पारदर्शी है।

वहाँ पाठ क्षेत्र के पाठ दिखाई किए बिना कैरट दिखाने के लिए एक तरीका है?

यदि मैं इसके बजाय टेक्स्टरेरा के ऊपर div बना देता हूं और इसे pointer-events: none देता हूं, तो टेक्स्टरेरा अभी भी नीचे दिखाई देता है। यह व्यवस्था चिकनी स्क्रॉलिंग को भी मुश्किल बनाती है, इसलिए यह मेरे लिए काम नहीं करती है।

उत्तर

3

बस अपनी खुद की देखभाल डालें!

function blink() { 
 
    document.getElementById('caret').hidden ^= 1; 
 
    blinkTimeout = setTimeout(blink, 500); 
 
} 
 
var mydiv = document.getElementById('mydiv'), 
 
    myta = document.getElementById('myta'), 
 
    blinkTimeout = setTimeout(blink, 500), 
 
    lastSelectionStart = 0, 
 
    lastSelectionEnd = 0, 
 
    whichSelection = true; 
 
function updateDiv() { 
 
    var fc; 
 
    while (fc = mydiv.firstChild) mydiv.removeChild(fc); 
 
    if (myta.selectionStart != lastSelectionStart) { 
 
    lastSelectionStart = myta.selectionStart; 
 
    whichSelection = false; 
 
    } 
 
    if (myta.selectionEnd != lastSelectionEnd) { 
 
    lastSelectionEnd = myta.selectionEnd; 
 
    whichSelection = true; 
 
    } 
 
    var cursorPos = whichSelection ? myta.selectionEnd : myta.selectionStart; 
 
    for (var i = 0; i < myta.value.length; i++) { 
 
    if (i == cursorPos) { 
 
     var caret = document.createElement('span'); 
 
     caret.id = 'caret'; 
 
     caret.appendChild(document.createTextNode('\xA0')); 
 
     mydiv.appendChild(caret); 
 
     clearTimeout(blinkTimeout); 
 
     blinkTimeout = setTimeout(blink, 500); 
 
    } 
 
    var span = document.createElement('span'); 
 
    span.className = Math.random() < 0.5 ? 'green' : 'red'; 
 
    span.appendChild(document.createTextNode(myta.value[i])); 
 
    mydiv.appendChild(span); 
 
    } 
 
    if (myta.value.length == cursorPos) { 
 
    var caret = document.createElement('span'); 
 
    caret.id = 'caret'; 
 
    caret.appendChild(document.createTextNode('\xA0')); 
 
    mydiv.appendChild(caret); 
 
    clearTimeout(blinkTimeout); 
 
    blinkTimeout = setTimeout(blink, 500); 
 
    } 
 
}; 
 
myta.addEventListener('input', updateDiv); 
 
myta.addEventListener('focus', updateDiv); 
 
myta.addEventListener('mousedown', function() { 
 
    setTimeout(updateDiv, 0); 
 
}); 
 
myta.addEventListener('keydown', function() { 
 
    setTimeout(updateDiv, 0); 
 
}); 
 
myta.addEventListener('blur', function() { 
 
    document.getElementById('caret').hidden = true; 
 
    clearTimeout(blinkTimeout); 
 
});
body { position: relative } 
 
div, textarea { 
 
    -webkit-text-size-adjust: none; 
 
    width: 100%; 
 
    white-space: pre-wrap; 
 
    word-wrap: break-word; 
 
    overflow-wrap: break-word; 
 
    font: 1rem sans-serif; 
 
    padding: 2px; 
 
    margin: 0; 
 
    border-radius: 0; 
 
    border: 1px solid #000; 
 
    resize: none; 
 
} 
 
textarea { 
 
    position: absolute; 
 
    top: 0; 
 
    color: transparent; 
 
    background: transparent; 
 
} 
 
.red { color: #f00 } 
 
.green { color: #0f0 } 
 
#caret { 
 
    display: inline-block; 
 
    position: absolute; 
 
    width: 1px; 
 
    background: #000; 
 
} 
 
#caret[hidden] { display: none }
<div id="mydiv"><span id="caret">&nbsp;</span></div> 
 
<textarea id="myta" autofocus=""></textarea>

मैं यहाँ एक <span>#caret div जो जे एस का उपयोग कर अपने छिपा विशेषता टॉगल करके हर 500ms ब्लिंक में डाला। ब्राउज़र के व्यवहार को दोहराने के लिए, मैं चाहे वह selectionStart या selectionEnd जो कैरट पर वास्तव में था का पता लगाने, और यह ठोस रह जबकि पाठ इनपुट किया जा रहा था करना था।

स्पैन निश्चित लंबाई की नहीं हैं या घोंसला वाले हैं, यह हासिल करना थोड़ा मुश्किल है, लेकिन सामग्री के साथ झुकाव करना अधिक जटिल हाइलाइटर के साथ आसान है। इस समारोह सही जगह पर कैरट से जोड़ दिया जाएगा:

function insertNodeAtPosition(node, refNode, pos) { 
    if (typeof(refNode.nodeValue) == 'string') refNode.parentNode.insertBefore(node, refNode.splitText(pos)); 
    else { 
     for (var i = 0; i < refNode.childNodes.length; i++) { 
      var chNode = refNode.childNodes[i]; 
      if (chNode.textContent.length <= pos && i != refNode.childNodes.length - 1) pos -= chNode.textContent.length; 
      else return insertNodeAtPosition(node, chNode, pos); 
     } 
    } 
} 

उपयोग (जहां i डालने के लिए स्थिति है):

var caret = document.createElement('span'); 
caret.id = 'caret'; 
caret.appendChild(document.createTextNode('\xA0')); 
insertNodeAtPosition(caret, mydiv, i); 
clearTimeout(blinkTimeout); 
blinkTimeout = setTimeout(blink, 500); 
1

क्यों बस एक <div contenteditable="true"></div> बजाय <textarea></textarea> का उपयोग नहीं?। इसके साथ आपको अतिरिक्त textarea की आवश्यकता नहीं है। demo here देखें।

HTML:

<div id="myta" autofocus="" contenteditable="true"></div> 

जावास्क्रिप्ट:

var myta = document.getElementById('myta'); 
function updateDiv() { 
    var fc; 
    var text = myta.innerText || myta.textContent; 
    while (fc = myta.firstChild) myta.removeChild(fc); 
    for (var i = 0; i < text.length; i++) { 
     var span = document.createElement('span'); 
     span.className = Math.random() < 0.5 ? 'green' : 'red'; 
     span.appendChild(document.createTextNode(text[i])); 
     myta.appendChild(span); 
    } 
    placeCaretAtEnd(myta); 
}; 
myta.addEventListener('input', updateDiv); 

इसके अलावा, अंत में कैरट स्थानांतरित करने के लिए जब आप नए पाठ div अंदर मैं this answer से कि समारोह के लिए इस्तेमाल किया डाल :

function placeCaretAtEnd(el) { 
    el.focus(); 
    if (typeof window.getSelection != "undefined" 
     && typeof document.createRange != "undefined") { 
     var range = document.createRange(); 
     range.selectNodeContents(el); 
     range.collapse(false); 
     var sel = window.getSelection(); 
     sel.removeAllRanges(); 
     sel.addRange(range); 
    } else if (typeof document.body.createTextRange != "undefined") { 
     var textRange = document.body.createTextRange(); 
     textRange.moveToElementText(el); 
     textRange.collapse(false); 
     textRange.select(); 
    } 
} 
+0

contenteditable एक ऐसा फ़ॉर्म तत्व नहीं है और के बाद से डेटा हानि हो सकती है इसकी सामग्री ब्राउज़र द्वारा सहेजी नहीं गई है। यह काम करने के लिए भी बहुत गन्दा है। – bjb568

+0

संबंधित: http://stackoverflow.com/questions/20728150/unusual-shape-of-a-textarea#comment31094671_20728150 और http://stackoverflow.com/questions/20728150/unusual-shape-of-a-textarea#comment31158616_20728275 – bjb568

+0

यदि आप 'textarea' भी चाहते हैं, तो [यह नया डेमो] देखें (https://jsfiddle.net/bb5jmw95/1/)। मैं केवल 'मायटा' जोड़ता हूं।मूल्य = पाठ; 'textarea' में पाठ सेट करने के लिए भी। फिर आप 'textarea' को 'डिस्प्ले: कोई नहीं;' के साथ आसानी से छुपा सकते हैं। आशा है कि यह मदद :) – lmgonzalves

संबंधित मुद्दे