1

I have the following working code: http://jsfiddle.net/henrichro/Z75wS/

When the user is selecting some text, left and right markers will appear, just like on iPhones for example. Selection is possible also backwards. The code was mainly built on the solution found here https://stackoverflow.com/a/15369695/621639 , of course changed a little bit, converted the jQuery into JS, as my main goal is to write everything in JavaScript, instead of using any library.

What I need, is to make the markers draggable, so I can extend or shrink the selection.

Current JavaScript code:

function applySelectionMarkers() {

    if( !window.getSelection().isCollapsed ) {

        var sel = window.getSelection();
        var range = document.createRange();
        range.setStart( sel.anchorNode, sel.anchorOffset );
        range.setEnd( sel.focusNode, sel.focusOffset );
        var backwards = range.collapsed;
        range.detach();

        var rects = sel.getRangeAt(0).getClientRects();
        var n = rects.length - 1;

        //console.log(rects);

        var lineHeight = getLineHeight( edit );

        var markerRight = document.getElementById( "markerRight" );
        var markerRightWidth = markerRight.offsetWidth;

        var markerLeft = document.getElementById( "markerLeft" );
        var markerLeftWidth = markerLeft.offsetWidth;


        if ( markerRightWidth == 0 ) {
            markerRightWidth = 10;
        }

        if ( markerLeftWidth == 0 ) {
            markerLeftWidth = 10;
        }

        if ( lastCharRTL( getSelectionHtml() ) ) {

            markerLeft.style.top = ( rects[0].top + lineHeight ) + "px";
            markerLeft.style.left = ( rects[0].left - markerLeftWidth ) + "px";
            markerLeft.style.display = "block";

            markerRight.style.top = ( rects[n].top + lineHeight ) + "px";
            markerRight.style.left = ( rects[n].left - markerRightWidth ) + "px";
            markerRight.style.display = "block";

            //alert( "one" + markerLeftWidth );

        } else if ( backwards ) {

            markerLeft.style.top = ( rects[n].top + lineHeight ) + "px";
            markerLeft.style.left = rects[n].right + "px";
            markerLeft.style.display = "block";

            markerRight.style.top = ( rects[0].top + lineHeight ) + "px";
            markerRight.style.left = ( rects[0].left - markerRightWidth ) + "px";
            markerRight.style.display = "block";

            //alert( "two" + markerRightWidth );

        } else {

            markerLeft.style.top = ( rects[0].top + lineHeight ) + "px";
            markerLeft.style.left = ( rects[0].left - markerLeftWidth ) + "px";
            markerLeft.style.display = "block";

            markerRight.style.top = ( rects[n].top + lineHeight ) + "px";
            markerRight.style.left = rects[n].right + "px";
            markerRight.style.display = "block";

            //alert( "three" + markerLeftWidth );
        }
    } else {
        markerLeft.style.display = "none";
        markerRight.style.display = "none";
    }
}

function getSelectionHtml() {
    var html = "";
    if ( typeof window.getSelection != "undefined" ) {
        var sel = window.getSelection();
        if ( sel.rangeCount ) {
            var container = document.createElement( "div" );
            for ( var i = 0, len = sel.rangeCount; i < len; ++i ) {
                container.appendChild( sel.getRangeAt(i).cloneContents() );
            }
            html = container.innerHTML;
        }
    } else if ( typeof document.selection != "undefined" ) {
        if ( document.selection.type == "Text" ) {
            html = document.selection.createRange().htmlText;
        }
    }
    return html;
}

function lastCharRTL( txt ) {
    return /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]$/.test(txt);
}

// line height in selectie ca putem adauga la markerLeft top attribute
function getLineHeight( element ){
    var temp = document.createElement( element.nodeName );
    temp.setAttribute( "style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize );
    temp.innerHTML = "test";
    temp = element.parentNode.appendChild( temp );
    var ret = temp.clientHeight;
    temp.parentNode.removeChild( temp );
    return ret;
}

document.onmouseup = function() {
    applySelectionMarkers();
}

function KeyPress(e) {
    var evtobj = window.event ? event : e;
    if ( evtobj.keyCode == 65 && evtobj.ctrlKey ) {
        console.log(evtobj.keyCode);
        applySelectionMarkers();
    }
}

document.onkeydown = KeyPress;

Further credits:

https://stackoverflow.com/a/5222955/621639, https://stackoverflow.com/a/4515470/621639

Update: Playing while dragging one of the markers:

window.onload = function() {
    draggable( 'markerLeft' );
}

var dragObj = null;

function draggable( id ) {
    var obj = document.getElementById( id );
    obj.style.position = "absolute";
    obj.onmousedown = function() {
        dragObj = obj;
    }
}

document.onmouseup = function(e) {
    dragObj = null;
}

document.onmousemove = function(e) {
    var x = e.pageX;
    var y = e.pageY;
    if( dragObj == null )
        return;
    dragObj.style.left = x + "px";
    dragObj.style.top = y + "px";
}

But when I drag the left marker (red), the whole selection disappears.

Community
  • 1
  • 1
  • Just the suggestion seen here: http://stackoverflow.com/a/19624089/621639 Without success. –  Oct 29 '13 at 09:10
  • Yes, I can drag an element, but in current scenario if I drag a marker, the selection disappears. I can copy paste the code snippet how I've tried the dragging, but also I would be more grateful if your comments could be more friendly. It is not an intelligent option to post an agressive or furious comment and then edit it. I haven't done anything bad for you ;) –  Oct 29 '13 at 09:28

0 Answers0