2015-12-04 15 views
16

Ho un div contenteditabile che mi piacerebbe poter consentire agli utenti di inserire elementi come collegamenti, immagini o video di YouTube. Al momento questo è quello che ho:Ottieni e imposta la posizione del cursore con div contenteditable

function addLink() { 
 
    var link = $('#url').val(); 
 
    $('#editor').focus(); 
 
    document.execCommand('createLink', false, link); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<!-- Text Editor --> 
 
<div id="editor" contenteditable="true"></div> 
 

 
<!-- Add Link --> 
 
<input type="text" id="url"> 
 
<button onclick="addLink()">Submit</button>

Come si può vedere, l'utente deve digitare in una casella di testo separato per immettere l'indirizzo di collegamento. Di conseguenza, quando il collegamento viene aggiunto all'editor, non viene aggiunto alla posizione in cui si trova il puntatore/cursore.

La mia domanda è come posso ottenere e impostare la posizione del puntatore/cursore. Ho visto altre domande come this for setting the pointer tuttavia preferirei avere una soluzione supportata in tutti i browser moderni, inclusi Chrome, Safari, Firefox e IE9 +.

Qualche idea? Grazie.

Edit:

Ho trovato il codice sotto che ottiene la posizione tuttavia, si ottiene solo la posizione secondo la linea è acceso. Per esempio, se ho avuto questo (dove | è il cursore):

This is some text 
And som|e more text 

Poi sarei tornato il valore 7, non 24.

function getPosition() { 
    if (window.getSelection) { 
     sel = window.getSelection(); 
     if (sel.getRangeAt) { 
      return sel.getRangeAt(0).startOffset; 
     } 
    } 
    return null; 
} 
+0

La soluzione a cui è collegato ha una soluzione che funziona su tutti i browser, basta leggere oltre quella accettata. Per ottenere la posizione del cursore, prova questo: http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-contain-html-content – SunKnight0

+0

@ SunKnight0 Ho provato il seguente codice dal soluzione fornita dall'utente tuttavia restituisce come sempre 0 .var editor = document.getElementById ('# editor'); ' ' console.log (getCaretCharacterOffsetWithin (editor)); 'Ho utilizzato la funzione da questa risposta http: // stackoverflow .com/questions/4811822/get-a-ranges-start-and-end-offset-relative-to-its-parent-container/4812022 # 4812022 –

+0

Utilizzare 'getElementById ('editor')'. Stai mescolando JavaScript vaniglia con JQuery. – SunKnight0

risposta

3

un buon editor rich-text è una delle cose più difficili da fare al momento, ed è praticamente un progetto di per sé (API ostile, enorme numero di casi d'angolo , differenze tra browser, la lista continua). Ti consiglio vivamente di provare e trovare una soluzione esistente.

Alcune librerie che possono essere utilizzati includono:

+0

Grazie per la tua risposta, tuttavia, voglio un semplice editor di testo piuttosto che un editor di codice come il mirror del codice. –

+1

Grazie per aver aggiunto Quill e WYSIHTML. Questi sembrano essere molto più adatti a ciò che hai delineato nella domanda. – SpeedySan

6

C'è un sacco di informazioni correlate in loco. Questo funziona per me e per i miei clienti.

DEMO

https://stackoverflow.com/a/6249440/2813224

function setCaret(line, col) { 
 
    var ele = document.getElementById("editable"); 
 
    var rng = document.createRange(); 
 
    var sel = window.getSelection(); 
 
    rng.setStart(ele.childNodes[line], col); 
 
    rng.collapse(true); 
 
    sel.removeAllRanges(); 
 
    sel.addRange(range); 
 
    ele.focus(); 
 
} 
 

 
//https://stackoverflow.com/a/6249440/2813224 
 

 
var line = document.getElementById('ln').value; 
 
var col = document.getElementById('cl').value; 
 
var btn = document.getElementById('btn'); 
 
btn.addEventListener('click', function(event) { 
 
    var lineSet = parseInt(line, 10); 
 
    var colSet = parseInt(col, 10); 
 
    setCaret(lineSet, colSet); 
 
}, true);
<div id="editable" contenteditable="true"> 
 
    <br/>text text text text text text 
 
    <br/>text text text text text text 
 
    <br/>text text text text text text 
 
    <br/> 
 
    <br/> 
 
</div> 
 
<fieldset> 
 
    <button id="btn">focus</button> 
 
    <input type="button" class="fontStyle" onclick="document.execCommand('italic',false,null);" value="I" title="Italicize Highlighted Text"> 
 
    <input type="button" class="fontStyle" onclick="document.execCommand('bold',false,null);" value="B" title="Bold Highlighted Text"> 
 
    <input id="ln" placeholder="Line#" /> 
 
    <input id="cl" placeholder="Column#" /> 
 
</fieldset>

2

ho cercato di trovare una soluzione,

Con un piccolo aiuto può essere perfezionato. È una combinazione di risposte che ho trovato su SO e la mia exp.

sua ingannevole, la sua disordinato ... ma se si deve, si può usare, ma richiede un po 'di lavoro per supportare i collegamenti interni (se cursore è su un ancoraggio che creerà ancora all'interno di ancoraggio)

Ecco il JS:

var lastPos; 
var curNode = 0; 
function setCaret() { 
    curNode=0; 
    var el = document.getElementById("editor"); 
    var range = document.createRange(); 
    var sel = window.getSelection(); 

    console.log(el.childNodes); 
    if (el.childNodes.length > 0) { 
     while (lastPos > el.childNodes[curNode].childNodes[0].textContent.length) { 
     lastPos = lastPos - el.childNodes[curNode].childNodes[0].textContent.length; 
     curNode++; 

     } 
     range.setStart(el.childNodes[curNode].childNodes[0], lastPos); 
     range.collapse(true); 
     sel.removeAllRanges(); 
     sel.addRange(range); 
    } 
    el.focus(); 
}; 


function savePos() { 
    lastPos = getCaretCharacterOffsetWithin(document.getElementById('editor')); 
} 

function addLink() { 
    console.log(lastPos); 

    setCaret(); 
    console.log(getCaretCharacterOffsetWithin(document.getElementById('editor'))); 

    console.log('focus'); 

    // $("#editor").focus(); 
    var link = $('#url').val(); 
    document.execCommand('createLink', false, link); 

} 

function getCaretCharacterOffsetWithin(element) { 
    var caretOffset = 0; 
    var doc = element.ownerDocument || element.document; 
    var win = doc.defaultView || doc.parentWindow; 
    var sel; 
    if (typeof win.getSelection != "undefined") { 
    sel = win.getSelection(); 
    if (sel.rangeCount > 0) { 
     var range = win.getSelection().getRangeAt(0); 
     var preCaretRange = range.cloneRange(); 
     preCaretRange.selectNodeContents(element); 
     preCaretRange.setEnd(range.endContainer, range.endOffset); 
     caretOffset = preCaretRange.toString().length; 
    } 
    } else if ((sel = doc.selection) && sel.type != "Control") { 
    var textRange = sel.createRange(); 
    var preCaretTextRange = doc.body.createTextRange(); 
    preCaretTextRange.moveToElementText(element); 
    preCaretTextRange.setEndPoint("EndToEnd", textRange); 
    caretOffset = preCaretTextRange.text.length; 
    } 
    return caretOffset; 
} 

fiddle

0

Questo è quello che hai chiesto, nella tua taglia: nell'esempio seguente puoi vedere come rilevare il numero esatto di caratteri del punto reale in cui hai fatto clic con il mouse o n:

<!-- Text Editor --> 
    <div id="editor" class="divClass" contenteditable="true">type here some text</div> 


    <script> 



    document.getElementById("editor").addEventListener("mouseup", function(key) { 

alert(getCaretCharacterOffsetWithin(document.getElementById("editor"))); 

}, false); 


function getCaretCharacterOffsetWithin(element) { 
var caretOffset = 0; 
var doc = element.ownerDocument || element.document; 
var win = doc.defaultView || doc.parentWindow; 
var sel; 
if (typeof win.getSelection != "undefined") { 
    sel = win.getSelection(); 
    if (sel.rangeCount > 0) { 
     var range = win.getSelection().getRangeAt(0); 
     var preCaretRange = range.cloneRange(); 
     preCaretRange.selectNodeContents(element); 
     preCaretRange.setEnd(range.endContainer, range.endOffset); 
     caretOffset = preCaretRange.toString().length; 
    } 
} else if ((sel = doc.selection) && sel.type != "Control") { 
    var textRange = sel.createRange(); 
    var preCaretTextRange = doc.body.createTextRange(); 
    preCaretTextRange.moveToElementText(element); 
    preCaretTextRange.setEndPoint("EndToEnd", textRange); 
    caretOffset = preCaretTextRange.text.length; 
} 
return caretOffset; 
} 
</script> 
Problemi correlati