简体   繁体   English

选择滚动文本时,将Div放置在文本区域之外

[英]Div is placed outside the text-area when selected the scrolled text

In my scenario, I need to display a div (replace with stars) below the selected text. 在我的方案中,我需要在所选文本下方显示一个div(用星代替)。 Here I am facing problem. 我在这里面临问题。

When the text area is scrolled and the scrolled text is selected (ie; the text at the last of the text-area box), the div (replace with stars) is appeared out of the text-area. 当滚动文本区域并选择滚动的文本(即,文本区域框最后的文本)时,div(用星号代替)出现在文本区域之外。 But, I need to display inside the text-area. 但是,我需要在文本区域内显示。 It is working fine without scrolling. 无需滚动即可正常工作。

JavaScript: JavaScript:

var edits = [""];
var interval = true;
var maxHistorySize = 10;
var saveInterval = 3000;

function undo(e) {
    var evtobj = window.event ? window.event : e;
    if (evtobj.keyCode == 90 && evtobj.ctrlKey) {
        evtobj.preventDefault();
        var txtarea = document.getElementById("mytextarea");
        var previousText = edits.length === 1 ? edits[0] : edits.pop();
        if (previousText !== undefined) {
            txtarea.value = previousText;
        }
    }
}

$(document).ready(function () {
    var replaceDiv = document.createElement('div');
    replaceDiv.id = 'rplceTxtDiv';
    document.getElementsByTagName('body')[0].appendChild(replaceDiv);
    $('<div id="starsRplce"></div>').appendTo('#rplceTxtDiv');
    $("#starsRplce").click(function () {
        var txtarea = document.getElementById("mytextarea");
        var start = txtarea.selectionStart;
        var finish = txtarea.selectionEnd;
        var allText = txtarea.value;
        edits.push(allText);
        if (edits.length > maxHistorySize) edits.shift();
        var sel = allText.substring(start, finish);
        sel = sel.replace(/[\S]/g, "*");
        var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
        txtarea.value = newText;
        $('#rplceTxtDiv').offset({ top: 0, left: 0 }).hide();
    });
    replaceDiv.style.display = "none";
    $('<span id="closePopUp">&#735;</span>').appendTo('#rplceTxtDiv');
    $("#closePopUp").click(function () {
        $('#rplceTxtDiv').offset({ top: 0, left: 0 }).hide();
    })
    var rplceTxtDiv = $('#rplceTxtDiv');
    $('#mytextarea').on('select', function (e) {
        replaceDiv.style.display = "block";
        var txtarea = document.getElementById("mytextarea");
        var start = txtarea.selectionStart;
        var finish = txtarea.selectionEnd;
        rplceTxtDiv.offset(getCursorXY(txtarea, start, 20)).show();
        rplceTxtDiv.find('div').text('replace with stars');
    }).on('input', function () {
        if (interval) {
            interval = false;
            edits.push($(this).val());
            if (edits.length > maxHistorySize) edits.shift();
            setTimeout(() => interval = true, saveInterval);
        }
    });
    document.onkeydown = undo;
});

var getCursorXY = function getCursorXY(input, selectionPoint, offset) {
    var inputX = input.offsetLeft,
        inputY = input.offsetTop;
    var div = document.createElement('div');
    var copyStyle = getComputedStyle(input);
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;
    try {
        for (var _iterator = copyStyle[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done) ; _iteratorNormalCompletion = true) {
            var prop = _step.value;

            div.style[prop] = copyStyle[prop];
        }
    } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
    } finally {
        try {
            if (!_iteratorNormalCompletion && _iterator.return) {
                _iterator.return();
            }
        } finally {
            if (_didIteratorError) {
                throw _iteratorError;
            }
        }
    }
    var swap = '.';
    var inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value;
    var textContent = inputValue.substr(0, selectionPoint);
    div.textContent = textContent;
    if (input.tagName === 'TEXTAREA') div.style.height = 'auto';
    if (input.tagName === 'INPUT') div.style.width = 'auto';
    var span = document.createElement('span');
    span.textContent = inputValue.substr(selectionPoint) || '.';
    div.appendChild(span);
    document.body.appendChild(div);
    var spanX = span.offsetLeft,
        spanY = span.offsetTop;
    document.body.removeChild(div);
    return {
        left: inputX + spanX,
        top: inputY + spanY + offset
    };
};

Here is my plunker . 这是我的朋克

You need to take the amount by which the textarea content has been scrolled into account in your position calculation as well, via the scrollTop property: 您还需要通过scrollTop属性考虑到文本区域内容在位置计算中的滚动量:

var inputX = input.offsetLeft,
    inputY = input.offsetTop,
    inputScrollOffset = input.scrollTop;

.

return {
    left: inputX + spanX,
    top: inputY - inputScrollOffset + spanY + offset
};

https://plnkr.co/edit/7ScbeTL88tWDU3PqzGqY?p=preview https://plnkr.co/edit/7ScbeTL88tWDU3PqzGqY?p=preview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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