简体   繁体   中英

Javascript move entire span with arrow keys

I am attempting to move span tags and their contents to the left or right by one position when the cursor is inside of them and Ctrl Right or Control Left is pressed. The span tags are inside of a contenteditable paragraph. I am not even having any luck getting a test message to log to the console to indicate that the cursor is even inside of the span tag. Here is the fiddle:

https://jsfiddle.net/scooke/5tp5oe7z/

Javascript/Jquery

$(document).on('keyup','.move',function(e){ 
  if (e.ctrlKey && (e.which === 37 || e.which === 39)){
    //move character at right or left of span to the other side
    //to simulate the whole span moved  
  }    
  e.stopPropagation();   
 });

Sample Html

<p class="parent" contenteditable="true">Bacon ipsum dolor amet jowl chicken    pork loin <span class="move">[move text]</span>tail. Short ribs meatball
<br>bresaola beef boudin hamburger, cow rump swine. Pork belly ribeye leberkas venison
<br>ground <span class="move">[move text]</span>round</p>
  1. Your code fails because (unfortunately) span elements do not fire keydown / keyup / keypress events - no, not even when they are part of a contenteditable .

    Therefore, you need to catch the event on the contenteditable element itself.

  2. Handling TextNode s in jQuery is as complicated (or more complicated) as doing it in native JS

    Relevant properties & methods of the standard Node class:

    • Node.prototype.data - content of the (text) node
    • Node.prototype.length - length of the content
    • Text.prototype.insertContent(position, content) - insert text
    • Text.prototype.appendConent(content) - append text
    • Text.prototype.deleteContent(position, length) - delete part of the content

That being said, this should provide the Ctrl+left/right-moving you expect: (JSFiddle)

$('p[contenteditable]').on('keydown', function (e) { 
    // Only handle event if ctrl+left / ctrl+right
    if (!e.ctrlKey || (e.which != 37 && e.which != 39)) return;
    // and selection is in a span.move
    var sel = document.getSelection();
    var node = sel.anchorNode;
    if (!node || node != sel.focusNode) return;
    // Text "[move text]" is in selection, get <span> parent
    if (node.nodeType == Node.TEXT_NODE) {
        node = node.parentNode;
    }
    if (!node || node.nodeName != 'SPAN' || node.className != 'move') return;

    // Do the magic
    moveSpan(node, e.which == 37); // 37: left, 39: right
    e.preventDefault();
    e.stopPropagation();
});

function moveSpan (span, toLeft) {
    var left = span.previousSibling;
    var right = span.nextSibling;

    if (!left || left.nodeType != Node.TEXT_NODE || !right || right.nodeType != Node.TEXT_NODE) return;
    if (toLeft && !left.length) return;
    if (!toLeft && !right.length) return;

    if (toLeft) {
        right.insertData(0, left.data[left.length - 1]);
        left.deleteData(left.length - 1, 1);
    } else {
        left.appendData(right.data[0]);
        right.deleteData(0, 1);
    }
}

Note: Only works on IE9+, the selection API on IE8- is non-standard.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM