2013-06-25 28 views
5

Jak ustawić pozycję na pozycji kursora w polu tekstowym? Znalazłem to pytanie było już zadawane tutaj wiele razy, ale nie mogę w stanie dowiedzieć się prawidłowego rozwiązania ..Jak ustawić pozycję na pozycji kursora w polu tekstowym?

to JSBIN

proszę mi pomóc ze swoimi sugestiami

góry dziękuję

+0

Nie mogę wymyślić, jak to zrobić w polu tekstowym, ponieważ nie można wstawić elementu w polu tekstowym. Możliwe jest użycie elementu div z 'contentEditable =" true "' i jakoś sformatować go tak, aby wyglądał jak pole tekstowe. Możesz określić offset za pomocą selectionStart, a następnie zastąp 'abcd [cursor] efgh' opcją' abcd

yourdiv
efgh'. Ponieważ tak naprawdę nie jest to odpowiedź na twoje pytanie, zostawię to jako komentarz. – Sumurai8

+0

Tak, próbowałem z contenteditable div ale dostałem uderzenie w wstawianiu innego div w pozycji kursora. Próbuję wstawić div, gdy wpisuję "@" w pozycji kursora i nie znalazłem sposobu, aby przejść ... Using .append() nie wstawi div w pozycji kursora, gdy wpisuję "@" gdziekolwiek w środku http://jsbin.com/uyufiw/25/edit – selvagsz

+0

'$ ('# cel'). selectionStart' lub coś podobnego może być użyte do znalezienia przesunięcia kursora, którego możesz użyć do utworzenia dwa podciągi. Jeden od początku do kursora, a drugi od kursora do końca. Możesz następnie zastąpić zawartość '$ ('# target')' 'firststring + yourdiv + laststring'. Aby wstawić coś, możesz zastąpić '

    ' z wybraną opcją. (To jest po prostu pół-składnia, ale coś w stylu 'this.parent.outerHTML = this.value' na li-elemencie.) Przykro mi, ale nie mogę naprawdę przetestować na tym komputerze, więc nie mogę tego zrobić dużo, ale daje tajemnicze wskazówki. – Sumurai8

    Odpowiedz

    0

    Możesz uzyskać pozycję myszy, a następnie przenieść listę rozwijaną do tej pozycji. Trzeba tylko upewnić się, że zawartość wyskakującego okienka ma wyższy indeks Z niż element, który ma zostać zamknięty, oraz że jego pozycja jest ustawiona na wartość bezwzględną.

    Oto mała próbka testowa, którą napisałem raz.

    <!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

    Jak czytam to, OP jest pytaniem, jak wyświetlić coś na pozycji kursora (czyli rzeczy, które wyświetla gdzie w polu tekstowym wpisywanego) -lub w inny words- jak uzyskać współrzędne kursora, * nie * gdzie mysz znajduje się, gdy użytkownik naciśnie klawisz i * nie * jak wyświetlić coś na tych współrzędnych. e.pageX nie istnieje dla zdarzenia keyDown. – Sumurai8

    +0

    Rzeczywiście. Właśnie to przeczytałem. Teraz wydaje się to tak jasne. To jest zupełnie inne pytanie od tego, na które niesłusznie odpowiedziałem. Dziękuję Ci. :) – enhzflep

    3

    wiem, że to nie jest dokładną odpowiedź na pytanie (rozwiązanie to nie korzysta z textarea, ale contentEditable div), ale nie sądzę, istnieje jakikolwiek sposób na uzyskanie współrzędnych XY za pomocą zdarzenia, atrybutu lub funkcji w obszarze tekstowym lub atrybutu lub funkcji w obiekcie Selection.

    Mam oczkach przykład on JSBin. Należy pamiętać, że nie przejmowałem się testowaniem zgodności w innych przeglądarkach i że nie zwróci to uwagi do miejsca, w którym zostało przerwane. Nie mogę wymyślić kodu na ten temat. Wierzę, że window.getSelection() nie będzie działać w IE, aw IE8 - byłoby zupełnie inaczej. Prawdopodobnie chcesz się upewnić, że menu nie będzie wyświetlane bezpośrednio z krawędzi ekranu.


    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> 
    

    CSS

    #target { 
        height: 100px; 
        border: 1px solid black; 
        margin-top: 50px; 
    } 
    
    #dummy { 
        display: inline-block; 
    } 
    
    .dropdown { 
        position: absolute; 
        top: 0; 
        left: 0; 
    } 
    

    kodu 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; 
        }); 
    }); 
    

    Wyjaśnienie

    Ten przykład działa w oparciu o które można wstawić element w contentEditable i odzyskać to przesunięcie do góry i po lewej stronie ekranu. Po naciśnięciu klawisza Shift + 50, procedura obsługi zdarzenia uniemożliwi zapisanie @, a zamiast tego wstawi sam obiekt atrapa @. Następnie pobieramy offset z tego obiektu i przesuwamy menu rozwijane do tego offsetu. Co więcej, zapisujemy offset znaków jako niestandardową właściwość menu, dzięki czemu możemy wstawić wartość w tej konkretnej lokalizacji. Następnie musimy usunąć dummy div, ale jeśli usuniemy manekina z $('#dummy').remove(), węzeł tekstowy przed manekinem i węzeł tekstowy za atrapą nie będzie się scalał. Spowoduje to skasowanie ostatniego węzła tekstowego, jeśli chcemy umieścić inny @ w innym miejscu i/lub umieścić go w niewłaściwym miejscu. Dlatego po prostu ponownie zamieniamy zawartość edytowalnego div. Na koniec, karetka musi zostać przywrócona do pierwotnej pozycji. Nie wiem, jak to zrobić właściwie.

    Drugi moduł obsługi polega na wstawianiu tekstu do pola tekstowego.Kod powinien być oczywisty. Ustawiona wcześniej właściwość x-custom-offset służy do wstawiania tekstu w odpowiednim miejscu w polu tekstowym. $('#dropdown').on('click', 'li a', function(e) { ... }); załączy zdarzenie click do ul zamiast li, aby działało, jeśli dynamicznie utworzysz li (ale będzie ono uruchamiane tylko wtedy, gdy klikniesz link).

    Powiązane problemy