2015-12-04 19 views
16

Mam contenteditable div, który chciałbym, aby użytkownicy mogli wstawiać takie rzeczy jak linki, obrazy lub filmy z YouTube. W tej chwili jest to, co mam:Zdobądź i ustaw pozycję kursora z contenteditable div

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>

Jak widać, użytkownik musi wpisać w oddzielnym polu tekstowym wpisać adres linku. W rezultacie, gdy link zostanie dodany do edytora, nie zostanie dodany do pozycji, w której znajdował się wskaźnik/karetka.

Moje pytanie brzmi: mogę uzyskać i ustawić lokalizację wskaźnika/karetki. Widziałem inne pytania, takie jak this for setting the pointer, ale wolałbym mieć rozwiązanie, które jest obsługiwane we wszystkich nowoczesnych przeglądarkach, w tym Chrome, Safari, Firefox i IE9 +.

Wszelkie pomysły? Dzięki.

Edit:

znalazłem poniższy kod, który pobiera pozycję jednak robi się tylko położenie według linii jest włączony. Na przykład, gdybym miał to (gdzie | jest kursor):

This is some text 
And som|e more text 

Następnie chciałbym być zwrócone wartości 7, nie 24.

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

Rozwiązanie, z którym łączyłeś się ma rozwiązanie, które działa we wszystkich przeglądarkach, po prostu przeczytaj poza akceptowanym. Jeśli chodzi o uzyskanie pozycji kursora, spróbuj tego: http://stackoverflow.com/questions/4767848/get-caret-cursor-position-in-contenteditable-area-containing-html-content – SunKnight0

+0

@ SunKnight0 Próbowałem następującego kodu z rozwiązanie, które podałeś, ale zwraca jak zwykle 0.'var editor = document.getElementById ('# editor'); ' ' console.log (getCaretCharacterOffsetWithin (editor)); 'Użyłem funkcji z tej odpowiedzi http: // stackoverflow .pl/questions/4811822/get-a-ranges-start-and-end-offset-relative-to-its-parent-container/4812022 # 4812022 –

+0

Użyj 'getElementById ('editor')'. Miksujesz wanilię JavaScript z JQuery. – SunKnight0

Odpowiedz

3

dobry edytor tekstu sformatowanego jest jednym z trudniejszych rzeczy do zrobienia tego, i to dość dużo projekt sam w sobie (nieprzyjazny API, ogromna liczba przypadków narożnych , różnice między przeglądarkami, lista jest długa). Zdecydowanie radzę spróbować znaleźć istniejące rozwiązanie.

Niektóre biblioteki, które mogą być stosowane, obejmują:

+0

Dziękuję za odpowiedź, ale chcę mieć prosty edytor tekstu, a nie edytor kodu, jak lustro kodu. –

+1

Dziękujemy za dodanie Quill i WYSIHTML. Wydaje się, że są one znacznie lepiej dopasowane do tego, co nakreśliłeś w pytaniu. – SpeedySan

6

Jest mnóstwo informacji powiązanych miejscu. Ten działa dla mnie i moich klientów.

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

Próbowałem znaleźć rozwiązanie,

Z niewielką pomocą może być udoskonalany. Jest to kombinacja odpowiedzi, które znalazłem na SO, a moje exp.

Jego trudne, jego niechlujny ... ale jeśli trzeba, można go używać, ale to wymaga trochę pracy, aby wspierać wewnętrzne linki (jeśli kursor znajduje się na kotwicy Stworzy kotwicy wewnątrz kotwicy)

Oto 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

to co prosiłeś, w twojej nagród: na poniższym przykładzie możesz zobaczyć, jak wykryć dokładną liczbę znaków rzeczywistego punktu, w którym kliknąłeś mysz 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> 
Powiązane problemy