Ich weiß, es auf der Frage keine genaue Antwort ist (diese Lösung keinen Textbereich verwendet, sondern eine contentEditable div), aber ich glaube nicht, gibt es eine Möglichkeit, xy-Koordinaten des Erhaltens Verwenden Sie entweder das Ereignis, ein Attribut oder eine Funktion für den Textbereich oder ein Attribut oder eine Funktion für das Selection-Objekt.
Ich habe ein Beispiel on JSBin vermascht. Bitte beachten Sie, dass ich mich nicht darum gekümmert habe, in anderen Browsern auf Kompatibilität zu testen, und dass das Caret nicht dorthin zurückkehrt, wo es aufgehört hat. Ich kann den Code dafür nicht herausfinden. Ich glaube, window.getSelection()
wird nicht in IE und in IE8 funktionieren - es wäre völlig anders. Wahrscheinlich möchten Sie auch sicherstellen, dass das Menü nicht direkt am Bildschirmrand angezeigt wird.
Die HTML
<div id="target" contentEditable="true">Type @ to see the dropdown.... </div>
<div class="dropdown">
<ul id="dropdown" class="dropdown-menu hide" role="menu" aria-labelledby="dropdownMenu">
<li><a>One</a> </li>
<li><a>Two</a></li>
<li><a>Three</a></li>
<li><a>Four</a> </li>
</ul>
</div>
Die CSS
#target {
height: 100px;
border: 1px solid black;
margin-top: 50px;
}
#dummy {
display: inline-block;
}
.dropdown {
position: absolute;
top: 0;
left: 0;
}
Die Javascript/JQuery
$("#target").keydown(function(e) {
if(e.which === 50 && e.shiftKey === true) {
//Prevent this event from actually typing the @
e.preventDefault();
//console.log(window.getSelection());
var sel = window.getSelection();
var offset = sel.baseOffset;
var node = sel.focusNode.parentNode;
//Get the text before and after the caret
var firsttext = node.innerHTML.substr(0,sel.baseOffset);
var nexttext = (sel.baseOffset != sel.focusNode.length) ? node.innerHTML.substr(sel.baseOffset, sel.focusNode.length) : "";
//Add in @ + dummy, because @ is not in there yet on keydown
node.innerHTML = firsttext + '@<div id="dummy"></div>' + nexttext;
//Transfer all relevant data to the dropdown menu
$('.dropdown').css('left', $('#dummy')[0].offsetLeft).css('top', $('#dummy')[0].offsetTop).prop('x-custom-offset', offset + 1);
//Delete the dummy to keep it clean
//This will split the contents into two text nodes, which we don't want
//$('#dummy').remove();
node.innerHTML = firsttext + '@' + nexttext;
//Put the caret back in place where we left off
//...I can't seem to figure out how to correctly set the range correctly...
$('#dropdown').removeClass('hide').addClass('show');
} else {
$('#dropdown').removeClass('show').addClass('hide');
$('.dropdown').removeProp('x-custom-offset');
}
});
$('#dropdown').on('click', 'li a', function(e) {
e.preventDefault();
$('#target').html(function(i, oldtext) {
var firsttext = oldtext.substr(0, $('.dropdown').prop('x-custom-offset'));
var nexttext = oldtext.substr($('.dropdown').prop('x-custom-offset'), oldtext.length);
console.log(e);
var inserttext = e.target.innerText;
//Cleanup
$('#dropdown').removeClass('show').addClass('hide');
return firsttext + inserttext + nexttext;
});
});
Die Erklärung
arbeitet an diesem Beispiel aus, dass Sie ein Element in einem contentEditable einfügen und abrufen können es an die Spitze und der linken Seite des Bildschirms versetzt wird. Wenn die Umschalt + Taste 50 gedrückt wird, verhindert der Event-Handler das Schreiben von @ und fügt stattdessen das @ + Dummy-Objekt selbst ein. Dann rufen wir den Offset von diesem Objekt ab und verschieben das Dropdown-Menü auf diesen Offset. Darüber hinaus speichern wir den Zeichen-Offset als eine benutzerdefinierte Eigenschaft x-custom-offset
des Menüs, so dass wir einen Wert an dieser bestimmten Stelle einfügen können. Dann müssen wir das Dummy-Div entfernen, aber wenn wir den Dummy mit $('#dummy').remove()
entfernen würden, würde der Textknoten vor dem Dummy und der Textknoten hinter dem Dummy nicht zusammengeführt. Dadurch wird der letzte Textknoten gelöscht, wenn wir ein anderes @ irgendwo platzieren und/oder an der falschen Stelle platzieren sollen. Daher ersetzen wir einfach den Inhalt des editierbaren div erneut. Zuletzt muss das Caret auf seine ursprüngliche Position zurückgesetzt werden. Ich kann mir aber nicht vorstellen, wie ich das richtig machen soll.
Der zweite Handler ist Text in das Textfeld einzufügen.Der Code sollte selbsterklärend sein. Die x-custom-offset
Eigenschaft, die wir zuvor festgelegt haben, wird hier verwendet, um den Text an der richtigen Stelle in das Textfeld einzufügen. $('#dropdown').on('click', 'li a', function(e) { ... });
wird das Klickereignis an die ul
anstelle der li
's anhängen, so dass es weiter funktioniert, wenn Sie die li
' s dynamisch erstellen (aber es wird nur ausgelöst, wenn Sie auf den Linkabschnitt klicken).
Ich kann mir keine Möglichkeit vorstellen, es in einem Textfeld zu tun, weil Sie ein Element nicht in ein Textfeld einfügen können. Was möglich ist, ist ein div mit 'contentEditable =" true "' zu verwenden und es irgendwie so zu formatieren, dass es wie eine Textbox aussieht. Sie können den Offset mit selectionStart bestimmen und dann 'abcd [cursor] efgh' durch' abcd
Ja, ich habe versucht mit contenteditable div aber wurde beim Einfügen eines anderen div an der Cursorposition getroffen. Ich versuche, ein Div einzufügen, wenn ich an der Cursor-Position '@' eintippe und keinen Weg gefunden habe ... .append() wird das Div nicht an der Cursor-Position einfügen, wenn ich '@' tippe irgendwo in der Mitte http://jsbin.com/uyufiw/25/edit – selvagsz
'$ ('# target'). selectionStart' oder etwas Ähnliches kann verwendet werden, um den Versatz des Cursors zu finden, den Sie zum Erstellen verwenden können zwei Teilstrings. Einer vom Anfang bis zum Cursor und einer vom Cursor bis zum Ende. Sie können dann den Inhalt von '$ ('# target')' durch 'firststring + yourdiv + lastring' ersetzen. Um etwas einzufügen, können Sie die '
' durch die gewählte Option ersetzen. (Dies ist nur Semisyntax, aber etwas wie 'this.parent.outerHTML = this.value' auf einem li-Element.) Auch Entschuldigung, aber ich kann nicht wirklich auf diesem Computer testen, so kann nicht tun viel, aber kryptische Hinweise geben. – Sumurai8