微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

css – 如何在textarea中的光标位置放置下拉列表?

如何将我的下拉列表放在textarea内的光标位置?我发现这个问题已经在这里问了很多次,但我无法弄清楚正确的解决方案..

这是JSBIN

请帮我提一下你的建议

提前致谢

解决方法

我知道这不是问题的确切答案(这个解决方案不使用textarea,而是使用contentEditable div),但我认为没有任何方法可以使用事件,属性获取xy坐标或者在textarea上运行或者在Selection对象上使用属性函数.

我已经编写了一个示例on JSBin.请注意,我没有打扰在其他浏览器中测试兼容性,并且它不会将插入符号返回到您停止的位置.我无法弄清楚代码.我相信window.getSelection()在IE中不起作用,而在IE8中它会完全不同.您可能也想确保菜单不会从屏幕边缘显示.

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

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

说明

此示例的工作原理是您可以在contentEditable中插入元素并将其偏移量检索到屏幕的顶部和左侧.当按下shift键50时,事件处理程序将阻止写入@,而是插入@ dummy对象本身.然后我们从该对象检索偏移量并将下拉菜单移动到该偏移量.此外,我们将字符偏移量保存为菜单自定义属性x-custom-offset,以便我们可以在该特定位置插入值.然后我们需要删除虚拟div,但是如果我们用$(‘#dummy’)删除虚拟对象.在虚拟之前删除()文本节点,虚拟对象后面的文本节点将不会合并.这将删除最后一个textnode,如果我们要在其他地方放置一个@和/或将它放在错误的位置.因此,我们只需再次替换可编辑div的内容.最后,插入符号必须回到它的原始位置.我无法弄清楚如何正确地做到这一点.

第二个处理程序是将文本插入文本框.代码应该是不言自明的.我们之前设置的x-custom-offset属性用于将文本插入文本框中的正确位置. $(‘#dropdown’).on(‘click’,’li a’,function(e){…});将click事件附加到ul而不是li,以便在动态创建li时它将继续工作(但只有在单击链接部分时才会触发).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。