Es gibt auch ein anderes Problem.
Die Lösung von Nico Burns funktioniert, wenn das contenteditable
div keine anderen mehrzeiligen Elemente enthält.
Wenn beispielsweise ein Div andere Divs enthält und diese anderen Divs andere Inhalte enthalten, können einige Probleme auftreten.
Um sie zu lösen, habe ich die folgende Lösung zusammengestellt, die eine Verbesserung der von Nico darstellt :
(function( cursorManager ) {
var voidNodeTags = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX'];
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
function canContainText(node) {
if(node.nodeType == 1) {
return !voidNodeTags.contains(node.nodeName);
} else {
return false;
}
};
function getLastChildElement(el){
var lc = el.lastChild;
while(lc && lc.nodeType != 1) {
if(lc.previousSibling)
lc = lc.previousSibling;
else
break;
}
return lc;
}
cursorManager.setEndOfContenteditable = function(contentEditableElement)
{
while(getLastChildElement(contentEditableElement) &&
canContainText(getLastChildElement(contentEditableElement))) {
contentEditableElement = getLastChildElement(contentEditableElement);
}
var range,selection;
if(document.createRange)
{
range = document.createRange();
range.selectNodeContents(contentEditableElement);
range.collapse(false);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
else if(document.selection)
{
range = document.body.createTextRange();
range.moveToElementText(contentEditableElement);
range.collapse(false);
range.select();
}
}
}( window.cursorManager = window.cursorManager || {}));
Verwendung:
var editableDiv = document.getElementById("my_contentEditableDiv");
cursorManager.setEndOfContenteditable(editableDiv);
Auf diese Weise wird der Cursor sicher am Ende des letzten Elements positioniert und schließlich verschachtelt.
EDIT # 1 : Um allgemeiner zu sein, sollte die while-Anweisung auch alle anderen Tags berücksichtigen, die keinen Text enthalten können. Diese Elemente werden als ungültige Elemente bezeichnet . In dieser Frage gibt es einige Methoden zum Testen, ob ein Element ungültig ist. Angenommen, es gibt eine Funktion namens canContainText
, die zurückgibt, true
wenn das Argument kein void-Element ist, die folgende Codezeile:
contentEditableElement.lastChild.tagName.toLowerCase() != 'br'
sollte ersetzt werden durch:
canContainText(getLastChildElement(contentEditableElement))
EDIT # 2 : Der obige Code wird mit allen beschriebenen und diskutierten Änderungen vollständig aktualisiert
Uncaught TypeError: Cannot read property 'nodeType' of null
erhalte eine Fehlermeldung bei Ihrer Funktion, sagt die Konsole, und dies kommt von der aufgerufenen Funktion getLastChildElement. Wissen Sie, was dieses Problem verursachen könnte?Die Lösung von Geowa4 funktioniert für einen Textbereich, jedoch nicht für ein inhaltsbearbeitbares Element.
Diese Lösung dient dazu, das Caret an das Ende eines inhaltsbearbeitbaren Elements zu verschieben. Es sollte in allen Browsern funktionieren, die contenteditable unterstützen.
function setEndOfContenteditable(contentEditableElement) { var range,selection; if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ { range = document.createRange();//Create a range (a range is a like the selection but invisible) range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start selection = window.getSelection();//get the selection object (allows you to change selection) selection.removeAllRanges();//remove any selections already made selection.addRange(range);//make the range you have just created the visible selection } else if(document.selection)//IE 8 and lower { range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start range.select();//Select the range (make it the visible selection } }
Es kann von Code verwendet werden, der ähnlich ist wie:
elem = document.getElementById('txt1');//This is the element that you want to move the caret to the end of setEndOfContenteditable(elem);
quelle
selectNodeContents
Teil von Nico gab mir Fehler sowohl in Chrome als auch in FF (testete keine anderen Browser), bis ich herausfand, dass ich anscheinend.get(0)
zu dem Element hinzufügen musste , dass ich die Funktion fütterte. Ich denke, das hat damit zu tun, dass ich jQuery anstelle von nacktem JS verwende. Ich habe dies von @jwarzech bei Frage 4233265 gelernt . Dank an alle!.get(0)
Ruft das dom-Element ab, das jQuery intern speichert. Sie können auch anhängen[0]
, was.get(0)
in diesem Zusammenhang gleichbedeutend ist .Wenn Sie sich nicht für ältere Browser interessieren, hat dieser den Trick für mich getan.
// [optional] make sure focus is on the element yourContentEditableElement.focus(); // select all the content in the element document.execCommand('selectAll', false, null); // collapse selection to the end document.getSelection().collapseToEnd();
quelle
document.execCommand
ist jetzt veraltet developer.mozilla.org/en-US/docs/Web/API/Document/execCommand .Es ist möglich, den Cursor durch den Bereich auf das Ende zu setzen:
setCaretToEnd(target/*: HTMLDivElement*/) { const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(target); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); target.focus(); range.detach(); // optimization // set scroll to the end if multiline target.scrollTop = target.scrollHeight; }
quelle
setCaretToEnd()
jedes Mal aufrufen - nur dann aufrufen, wenn Sie es benötigen: z. B. nach dem Kopieren und Einfügen oder nach dem Einschränken der Nachrichtenlänge.Ich hatte ein ähnliches Problem beim Versuch, ein Element bearbeitbar zu machen. In Chrome und FireFox war dies möglich, aber in FireFox ging das Caret entweder an den Anfang der Eingabe oder ein Leerzeichen nach dem Ende der Eingabe. Sehr verwirrend für den Endbenutzer, der versucht, den Inhalt zu bearbeiten.
Ich habe keine Lösung gefunden, indem ich verschiedene Dinge ausprobiert habe. Das einzige, was für mich funktionierte, war, "das Problem zu umgehen", indem ich eine einfache alte Texteingabe in meine einfügte. Jetzt funktioniert es. Es scheint, als ob "inhaltsbearbeitbar" immer noch auf dem neuesten Stand der Technik ist, die je nach Kontext möglicherweise so funktioniert, wie Sie es möchten.
quelle
Bewegen des Cursors zum Ende der bearbeitbaren Spanne als Reaktion auf das Fokusereignis:
moveCursorToEnd(el){ if(el.innerText && document.createRange) { window.setTimeout(() => { let selection = document.getSelection(); let range = document.createRange(); range.setStart(el.childNodes[0],el.innerText.length); range.collapse(true); selection.removeAllRanges(); selection.addRange(range); } ,1); } }
Und im Event-Handler aufrufen (Hier reagieren):
onFocus={(e) => this.moveCursorToEnd(e.target)}}
quelle
Das Problem mit
contenteditable
<div>
und<span>
ist behoben, wenn Sie es zunächst eingeben. Eine Problemumgehung hierfür könnte darin bestehen, ein Fokusereignis für Ihr div-Element und für diese Funktion auszulösen, das zu löschen und wieder aufzufüllen, was bereits im div-Element enthalten war. Auf diese Weise wird das Problem behoben und schließlich können Sie den Cursor mithilfe von Bereich und Auswahl am Ende platzieren. Hat für mich gearbeitet.moveCursorToEnd(e : any) { let placeholderText = e.target.innerText; e.target.innerText = ''; e.target.innerText = placeholderText; if(e.target.innerText && document.createRange) { let range = document.createRange(); let selection = window.getSelection(); range.selectNodeContents(e.target); range.setStart(e.target.firstChild,e.target.innerText.length); range.setEnd(e.target.firstChild,e.target.innerText.length); selection.removeAllRanges(); selection.addRange(range); } }
Im HTML-Code:
<div contentEditable="true" (focus)="moveCursorToEnd($event)"></div>
quelle