选择滚动文本时,Div位于文本区域之外

时间:2018-02-14 12:01:47

标签: javascript jquery html css

在我的场景中,我需要在所选文本下方显示div(替换为星号)。我在这里遇到问题。

当滚动文本区域并选择滚动文本时(即文本区域框最后的文本),div(替换为星号)出现在文本区域之外。但是,我需要在文本区域内显示。它没有滚动工作正常。

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
    };
};

这是我的plunker

1 个答案:

答案 0 :(得分:0)

您需要通过scrollTop属性获取在位置计算中滚动textarea内容的金额:

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