2

如何在另一个内容可编辑的 div 的内容中插入一个 div?父 div 是内容可编辑的,它包含字符串内容。当我在光标位置键入“@”时,我想插入另一个内容可编辑的 div。

例如,

 <div id="target" class="text-area" contenteditable='true'>This text can be anything... how to insert a div when i type start typing @... </div>

我想在输入“@”时插入另一个 div?我怎样才能做到这一点?

这是我尝试过的JSBIN

请帮我。提前致谢

4

4 回答 4

2

这似乎对我有用。我刚刚添加了 $(this).append(...)

$("#target").keydown(function(e) {

//  console.log(e, String.fromCharCode(e.which));

  if(e.which === 50 && e.shiftKey === true ){
      if(flag === true){
        flag = false;      
        return;
      }      
      flag = true;
    $(this).append('<div id="target2" contenteditable="true">New Div</div>');
      //console.log($('#target'),$('#target').prop('selectionStart'));
    } 
});
于 2013-06-25T15:00:03.767 回答
1

一种选择是检测“@”字符上的 keydown 事件,然后在当前光标位置放置一个绝对定位的 div。

获取光标位置是一段不错的代码。幸运的是,已经有人写了。代码如下:

function getTextAreaXandY() {



   // Don't do anything if key pressed is left arrow
    if (e.which == 37) return;     

    // Save selection start
    var selection = $(this).getSelection();
    var index = selection.start;

    // Copy text to div
    $(this).blur();
    $("div").text($(this).val());

    // Get current character
    $(this).setSelection(index, index + 1);
    currentcharacter = $(this).getSelection().text;

    // Get previous character
    $(this).setSelection(index - 1, index)
    previouscharacter = $(this).getSelection().text;

    var start, endchar;
    var end = 0;
    var range = rangy.createRange();

    // If current or previous character is a space or a line break, find the next word and wrap it in a span
    var linebreak = previouscharacter.match(/(\r\n|\n|\r)/gm) == undefined ? false : true;

    if (previouscharacter == ' ' || currentcharacter == ' ' || linebreak) {
        i = index + 1; // Start at the end of the current space        
        while (endchar != ' ' && end < $(this).val().length) {
            i++;
            $(this).setSelection(i, i + 1)
            var sel = $(this).getSelection();
            endchar = sel.text;
            end = sel.start;
        }

        range.setStart($("div")[0].childNodes[0], index);
        range.setEnd($("div")[0].childNodes[0], end);
        var nextword = range.toHtml();
        range.deleteContents();
        var position = $("<span id='nextword'>" + nextword + "</span>")[0];
        range.insertNode(position);
        var nextwordtop = $("#nextword").position().top;
    }

    // Insert `#caret` at the position of the caret
    range.setStart($("div")[0].childNodes[0], index);
    var caret = $("<span id='caret'></span>")[0];
    range.insertNode(caret);
    var carettop = $("#caret").position().top;

    // If preceding character is a space, wrap it in a span
    if (previouscharacter == ' ') {
        range.setStart($("div")[0].childNodes[0], index - 1);
        range.setEnd($("div")[0].childNodes[0], index);
        var prevchar = $("<span id='prevchar'></span>")[0];
        range.insertNode(prevchar);
        var prevchartop = $("#prevchar").position().top;
    }

    // Set textarea selection back to selection start
    $(this).focus();
    $(this).setSelection(index, selection.end);

    // If the top value of the previous character span is not equal to the top value of the next word,
    // there must have been some wrapping going on, the previous character was a space, so the wrapping
    // would have occured after this space, its safe to assume that the left and top value of `#nextword`
    // indicate the caret position
    if (prevchartop != undefined && prevchartop != nextwordtop) {
        $("label").text('X: ' + $("#nextword").position().left + 'px, Y: ' + $("#nextword").position().top);
        $('ul').css('left', ($("#nextword").position().left) + 'px');
        $('ul').css('top', ($("#nextword").position().top + 13) + 'px');
    }
    // if not, then there was no wrapping, we can take the left and the top value from `#caret`    
    else {
        $("label").text('X: ' + $("#caret").position().left + 'px, Y: ' + $("#caret").position().top);
        $('ul').css('left', ($("#caret").position().left) + 'px');
        $('ul').css('top', ($("#caret").position().top + 14) + 'px');
    }

    $('ul').css('display', 'block');
}

$("textarea").click(getTextAreaXandY);
$("textarea").keyup(getTextAreaXandY);

他们的小提琴在这里,它是为了回答这个问题而写的。

小提琴包括在当前光标位置放置一个新的 div。

于 2013-06-25T16:12:10.907 回答
0

我修改了 onKeyDown 事件监听器。将 keydown 事件绑定到 id 等于 target 的 div。

希望这对你有帮助。 http://jsbin.com/ilikay/4/edit

于 2013-06-25T15:10:32.393 回答
-1

终于有办法达到它了......这就是我做到的......

  1. 使用 selectionStart 获取 textarea 中光标位置处的字符串索引
  2. 将字符串从索引 0 切片到光标位置
  3. 将其插入跨度(因为跨度有多个边框框)
  4. 使用 element.getClientRects() 相对于视口获取边框框的尺寸。(这里是MDN 参考
  5. 计算顶部和左侧并将其提供给下拉列表

这适用于所有最新的浏览器。没有在旧的测试

这是工作箱

于 2013-06-27T17:31:36.843 回答