有没有办法阻止 contentEditable 元素在光标到达底部时滚动?

发布于 2025-01-02 02:50:20 字数 533 浏览 4 评论 0原文

例如,我有一个 contentEditable div,我可以在其中输入内容。当文本到达 div 底部时,浏览器会自动滚动 div,以便文本末尾和光标仍然可见。

如何防止 div 滚动,以便输入的文本超出 div 的底部,从而在键入时不再看到光标?

我想要实现的行为就像在 Photoshop 中一样:当您创建一个文本框并输入太多内容时,光标会继续越过框的底部,并且您看不到正在输入的内容。如果展开该框,您将看到所有隐藏的文本。

编辑 2/7/2012 9:27am: 这是我现在所拥有的,但它看起来有点问题,因为滚动位置是在 keyup 事件之后调整的: http://jsfiddle.net/trusktr/hgkak/6/ 所以在 keyup 事件之前,光标会暂时变得放置在视图中(对于每次击键)。我希望没有跳跃,并且当有多余的文本而视图没有跳跃时,光标保持在绿色 div 的末尾下方(跳跃对我来说似乎是一个业余黑客:D)

For example, I have a contentEditable div and I can type in it. When the text reaches the bottom of the div, the browser automatically scrolls the div so that the end of the text and the cursor are still visible.

How do I prevent the div from scrolling so that the inputted text goes past the bottom of the div and so that you can no longer see the cursor while you type?

The behavior I'm trying to achieve is like in Photoshop: when you make a text box, and type too much, the cursor continues past the bottom of the box and you can't see what you are typing. If you expand the box, you'll see all the hidden text.

EDIT 2/7/2012 9:27am: This is what I have right now, but it looks glitchy because the scroll position is adjusted AFTER the keyup event: http://jsfiddle.net/trusktr/hgkak/6/ So before the keyup event, the cursor gets temporarily placed into view (for each keystroke). I'd like there to be no jumping, and for the cursor to remain below the end of the green div when there is excess text without the view jumping around (the jumping seems like an amateur hack on my part :D)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一腔孤↑勇 2025-01-09 02:50:20

让我们尝试一下破解:

  • 首先,每当用户按下某个键时,我们都会尝试阻止或恢复任何滚动,
  • 我们将元素的 overflow 属性设置为 visible 以避免内容滚动,但是同时通过将其 opacity 设置为 0 来隐藏该元素。之后我们立即将 overflow 切换回 hidden 并再次显示该元素。
  • 为了避免闪烁,我们创建可编辑元素的克隆(使用 overflow:hidden)并在原始元素隐藏时显示该元素。

我们开始吧(使用 jQuery 来方便 DOM):

$(function() {

    var editableElement = $('#editable'), clonedElement;

    // Revert any scrolling                    
    editableElement.on("scroll", function(event) {
        editableElement.scrollTop(0);

        // Try to prevent scrolling completely (doesn't seem to work)
        event.preventDefault();
        return false;
    });

    // Switch overflow visibility on and off again on each keystroke.
    // To avoid flickering, a cloned element is positioned below the input area
    // and switched on while we hide the overflowing element.
    editableElement.on("keydown", function() {

        // Create a cloned input element below the original one
        if (!clonedElement) {
            var zIndex = editableElement.css('zIndex');
            if (isNaN(parseInt(zIndex, 10))) {
                zIndex = 10;
                editableElement.css({zIndex: zIndex});
            }    

            clonedElement = editableElement.clone();
            clonedElement.css({
                zIndex: zIndex-1,
                position: 'absolute',
                top: editableElement.offset().top,
                left: editableElement.offset().left,
                overflow: 'hidden',
                // Set pseudo focus highlighting for webkit
                // (needs to be adapted for other browsers)
                outline: 'auto 5px -webkit-focus-ring-color'
            });
            editableElement.before(clonedElement);
        } else {
            // Update contents of the cloned element from the original one
            clonedElement.html(editableElement.html());
        }

        // Here comes the hack:
        //   - set overflow visible but hide element via opactity.
        //   - show cloned element in the meantime
        clonedElement.css({opacity: 1});
        editableElement.css({overflow: 'visible', opacity: 0});

        // Immediately turn of overflow and show element again.
        setTimeout(function() {
            editableElement.css({overflow: 'hidden', opacity: 1});
            clonedElement.css({opacity: 0});
        }, 10);

    });
});

检查 this jsFiddle 来使用上面的代码。

请注意,这可能不是一个完整的解决方案(我只在 Safari、Chrome 和 Firefox 上尝试过),但对于经过测试的浏览器来说,它似乎有效。您可能想要微调和完善您的实现(例如焦点突出显示)。在 jsFiddle 示例中,我还关闭了拼写检查以避免标记闪烁。

Let's try a hack:

  • first we try to prevent or revert any scrolling
  • whenever the user presses a key we turn the element's overflow property to visible to avoid scrolling of the content, but hide the element at the same time by setting its opacity to 0. Immediately afterwards we switch overflow back to hidden and show the element again.
  • to avoid flickering we create a clone of the editable element (with overflow: hidden) and show this element while the original one is hidden.

Here we go (uses jQuery for DOM convenience):

$(function() {

    var editableElement = $('#editable'), clonedElement;

    // Revert any scrolling                    
    editableElement.on("scroll", function(event) {
        editableElement.scrollTop(0);

        // Try to prevent scrolling completely (doesn't seem to work)
        event.preventDefault();
        return false;
    });

    // Switch overflow visibility on and off again on each keystroke.
    // To avoid flickering, a cloned element is positioned below the input area
    // and switched on while we hide the overflowing element.
    editableElement.on("keydown", function() {

        // Create a cloned input element below the original one
        if (!clonedElement) {
            var zIndex = editableElement.css('zIndex');
            if (isNaN(parseInt(zIndex, 10))) {
                zIndex = 10;
                editableElement.css({zIndex: zIndex});
            }    

            clonedElement = editableElement.clone();
            clonedElement.css({
                zIndex: zIndex-1,
                position: 'absolute',
                top: editableElement.offset().top,
                left: editableElement.offset().left,
                overflow: 'hidden',
                // Set pseudo focus highlighting for webkit
                // (needs to be adapted for other browsers)
                outline: 'auto 5px -webkit-focus-ring-color'
            });
            editableElement.before(clonedElement);
        } else {
            // Update contents of the cloned element from the original one
            clonedElement.html(editableElement.html());
        }

        // Here comes the hack:
        //   - set overflow visible but hide element via opactity.
        //   - show cloned element in the meantime
        clonedElement.css({opacity: 1});
        editableElement.css({overflow: 'visible', opacity: 0});

        // Immediately turn of overflow and show element again.
        setTimeout(function() {
            editableElement.css({overflow: 'hidden', opacity: 1});
            clonedElement.css({opacity: 0});
        }, 10);

    });
});

Check this jsFiddle to play with the above code.

Note that this may not be a complete solution (I have only tried it with Safari, Chrome and Firefox yet), but for the tested browsers it seems to work. You may want to fine-tune and polish your implementation (e.g. focus highlighting). In the jsFiddle example I have also turned off spell checking to avoid flickering markings.

巾帼英雄 2025-01-09 02:50:20

您需要有具有 overflow:hidden;position:relative 和静态高度或最小高度的父 div (A)。

在这个父级中,您有子级 div (B),其中包含 contenteditable="true"style="position:absolute;width:100%;left:0;top:0" >

div A 的高度必须类似于 integer * div B 的行高


之后,您需要包含 rangy 和 jQuery库

Bind on div B keyup event function{

使用 rangey 在当前光标处创建空 span

从此跨度获取 offset().top 并将其与 offset().top + 进行比较outerHeight() 来自 div A。如果第一个很大然后第二个->您需要向下滚动 div B。

要向下滚动,只需更改 += div B 的 line-height 上的当前 css top

销毁空跨度。

(如果光标位置失败 -> 您需要在创建跨度之前预先保存它,并在销毁跨度后恢复光标位置)

}


此外,您还需要使用箭头键模拟所有内容。在这种情况下,您需要在 div B 中的 keyup 上使用 event.which 创建开关选择器。位于此处

如果光标位置超出 div A 的可见范围,则滚动(算法类似于我上面写的)


是的,这不是一个简单的方法,但它有效

You need to have parent div (A) with overflow:hidden;position:relative and static height or min-height.

Inside this parent you have children div (B) with contenteditable="true" and style="position:absolute;width:100%;left:0;top:0"

Height of div A must be like integer * line-height of div B


After that you need to include rangy and jQuery library

Bind on div B keyup event function{

Use rangy for create in current cursor place empty span.

Get offset().top from this span and compare it with offset().top +outerHeight() from div A. If first is large then second -> you need to scroll down div B.

To scroll down just change current css top on += line-height of div B

Destroy empty span.

(if cursor position fails -> you need to previously save it before creating span and restore cursor position after destroying span)

}


Also you need to emulate all with arrow keys. In that case you need to create switch selector with event.which on keyup in div B. Keycodes are here.

Scroll if cursor position is out from visible range in div A (algorithm similar to what I wrote above)


Yes, this is not an easy way, but it works

电影里的梦 2025-01-09 02:50:20

尝试设置 style="overflow:hidden;"在 div 上

Try setting style="overflow:hidden;" on the div

苦行僧 2025-01-09 02:50:20

添加一个与底部重叠并具有更高 z-index 的 Div?您可以将可编辑区域设置得非常高,以免造成影响。然后你必须使覆盖 div 可拖动。

Add a Div that overlaps the bottom with a higher z-index? You can either make the editable area very tall as to not make a difference. Then you'd have to make the covering div dragable.

怕倦 2025-01-09 02:50:20

很简单:

<div id="mydiv" contenteditable="true" style="width: 200px; height: 100px;"></div>


$(document).ready(function(){

    $("#mydiv").height(document.getElementById('mydiv').scrollHeight);

    $("#mydiv").keyup(function(){

        $(this).height(0).height(document.getElementById('mydiv').scrollHeight);

    });

});

Very simple:

<div id="mydiv" contenteditable="true" style="width: 200px; height: 100px;"></div>


$(document).ready(function(){

    $("#mydiv").height(document.getElementById('mydiv').scrollHeight);

    $("#mydiv").keyup(function(){

        $(this).height(0).height(document.getElementById('mydiv').scrollHeight);

    });

});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文