2013-06-25 9 views
5

Wie kann ich mein Dropdown an der Cursorposition in einem Textfeld positionieren? Ich habe diese Frage wurde hier schon oft gefragt gefunden, aber ich kann nicht der Lage, herauszufinden, die richtige Lösung ..Wie kann ich ein Dropdown an der Cursorposition in einem Textfeld positionieren?

dies die mir JSBIN

ist bitte helfen Sie mit Ihren Vorschlägen

Vielen Dank im Voraus

+0

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

yourdiv
efgh' ersetzen. Da es sich nicht wirklich um eine Antwort auf Ihre Frage handelt, überlasse ich es als Kommentar. – Sumurai8

+0

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

+0

'$ ('# 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

    Antwort

    0

    Sie können die Position der Maus abrufen und dann die Dropdown-Liste an diese Position verschieben. Sie müssen nur sicherstellen, dass der Popup-Inhalt einen höheren Z-Index hat als das Element, das Sie verdecken möchten, und dass seine Position auf absolut eingestellt ist.

    Hier ist eine kleine Testprobe, die ich einmal geschrieben habe.

    <!DOCTYPE html> 
    <html> 
    <head> 
    <script> 
    function byId(e){return document.getElementById(e);} 
    function newEl(tag){return document.createElement(tag);} 
    function newTxt(txt){return document.createTextNode(txt);} 
    function toggleClass(element, newStr) 
    { 
        index=element.className.indexOf(newStr); 
        if (index == -1) 
         element.className += ' '+newStr; 
        else 
        { 
         if (index != 0) 
          newStr = ' '+newStr; 
         element.className = element.className.replace(newStr, ''); 
        } 
    } 
    function forEachNode(nodeList, func) 
    { 
        var i, n = nodeList.length; 
        for (i=0; i<n; i++) 
        { 
         func(nodeList[i], i, nodeList); 
        } 
    } 
    
    window.addEventListener('load', mInit, false); 
    
    function mInit() 
    { 
    } 
    
    function onShowBtn(e) 
    { 
        var element = byId('popup'); 
        element.className = element.className.replace(' hidden', ''); 
        var str = '';//'border-radius: 32px; border: solid 5px;'; 
        e = e||event; 
        str += "left: " + e.pageX + "px; top:"+e.pageY+"px;" 
        element.setAttribute('style',str); 
    } 
    function onHideBtn() 
    { 
        var element = byId('popup'); 
        if (element.className.indexOf(' hidden') == -1) 
         element.className += ' hidden'; 
    } 
    
    </script> 
    <style> 
    #controls 
    { 
        display: inline-block; 
        padding: 16px; 
        border-radius: 6px; 
        border: solid 1px #555; 
        background: #AAA; 
    } 
    #popup 
    { 
        border: solid 1px #777; 
        border-radius: 4px; 
        padding: 12px; 
        background: #DDD; 
        display: inline-block; 
        z-index: 2; 
        position: absolute; 
    } 
    #popup.hidden 
    { 
        visibility: hidden; 
    } 
    </style> 
    </head> 
    <body> 
        <div id='controls'> 
         <input type='button' value='show' onclick='onShowBtn()'> 
         <input type='button' value='hide' onclick='onHideBtn()'> 
        </div> 
        <br> 
        <div id='popup'> 
         <p>This is some assorted 
          text</p> 
          <hr> 
         <ul> 
          <li>item a</li> 
          <li>item 2</li> 
          <li>item iii</li> 
         </ul> 
        </div> 
    </body> 
    </html> 
    
    +1

    Wie ich es gelesen habe, fragt OP, wie man etwas an der Position des Cursors anzeigt (das Ding, das anzeigt, wo in einem Textfeld du schreibst) - oder mit anderen Worten - wie man die Koordinaten des Cursors erhält, * nicht * wo die Maus ist, wenn der Benutzer eine Taste drückt und * nicht * wie man etwas auf diesen Koordinaten anzeigt. e.pageX existiert nicht für das keyDown-Ereignis. – Sumurai8

    +0

    In der Tat. Ich habe es gerade neu gelesen. Es scheint jetzt so klar zu sein. Das ist eine ganz andere Frage als die, die ich falsch beantwortet habe. Vielen Dank. :) – enhzflep

    3

    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).

    Verwandte Themen