How can I best do an inline drag range in a paragraph of text?

I have a paragraph of text where the user can place a "contact" to mark a position. Once the contact has been placed, I would like to allow the user to move their position by dragging and dropping them to a new location in the paragraph. This is easy to do with block elements, but I have yet to see a good way to do it with inline elements. How can i do this?

I've already implemented it using window.selection to find the location of the cursor in a paragraph, but it's not as smooth as I would like.

As a side note, I'm using the Rangy library to wrap my own Range and Selection functionality, but it works the same as the native functions.

Here is the code:

$(document).on("mousedown", '.pin', function () {
    //define what a pin is
    var el = document.createElement("span");
    el.className = "pin";
    el.id = "test";
    //make it contain an empty space so we can color it
    el.appendChild(document.createTextNode("d"));
    $(document).on("mousemove", function () {
        //get the current selection
        var selection = rangy.getSelection();
        //collapse the selection to either the front
        //or back, since we do not want the user to see it.
        if (selection.isBackwards()) {
            selection.collapseToStart();
        } else {
            selection.collapseToEnd();
        }
        //remove the old pin
        $('.pin').remove();
        //place the new pin at the current selection
        selection.getAllRanges()[0].insertNode(el);
    });
    //remove the handler when the user has stopped dragging it
    $(document).on("mouseup", function () {
        $(document).off("mousemove");
    });
});

      

And here is a working demo: http://jsfiddle.net/j1LLmr5b/22/ .

As you can see, it works (normally), but the user can see the selected selection. Any ideas on how to move the span without selecting it? I'll also settle for an alternative method that doesn't use selection at all. The goal is to allow the span to move as much as possible.

+3


source to share


3 answers


You can do this using ranges, instead using code similar to this answer . Unfortunately the code is a little longer than ideal because IE hasn't implemented it yet document.caretPositionFromPoint()

. However, an old rescue object TextRange

still present in IE 11 comes to the rescue.

Here's a demo:

http://jsfiddle.net/j1LLmr5b/26/



Here's the relevant code:

var range, textRange, x = e.clientX, y = e.clientY;

//remove the old pin
$('.pin').remove();

// Try the standards-based way first
if (document.caretPositionFromPoint) {
    var pos = document.caretPositionFromPoint(x, y);
    range = document.createRange();
    range.setStart(pos.offsetNode, pos.offset);
    range.collapse();
}
// Next, the WebKit way
else if (document.caretRangeFromPoint) {
    range = document.caretRangeFromPoint(x, y);
}
// Finally, the IE way
else if (document.body.createTextRange) {
    textRange = document.body.createTextRange();
    textRange.moveToPoint(x, y);
    var spanId = "temp_" + ("" + Math.random()).slice(2);
    textRange.pasteHTML('<span id="' + spanId + '">&nbsp;</span>');
    var span = document.getElementById(spanId);
    //place the new pin
    span.parentNode.replaceChild(el, span);
}
if (range) {
    //place the new pin
    range.insertNode(el);
}

      

+1


source


Try this friend of mine

el.appendChild(document.createTextNode("d"));

      



You have created an empty span tag that you think is empty.

+1


source


add after el.id = "test";

this

 var value = $('.pin').text();
 $(el).text(value);

      

You can hide the selection with css

 ::selection {color:red;background:yellow;}
 ::-moz-selection {color:red;background:yellow;} 

      

that's all how can i help now

+1


source







All Articles