Ace Cloud 9编辑器如何自动调整高度以适应内容?

69

我试图将Ace编辑器添加到页面中,但我不知道如何根据其内容长度自动设置其高度。

理想情况下,当内容更改时,高度会重新计算,但如果在页面加载时仅设置高度,我也会很满意。

对于JavaScript新手,有人可以帮助我确定代码的长度,它跨越了多少行,新高度是多少,以及如何更新DOM以反映此信息吗?

我在Google小组中找到了这个建议,但是我真的不明白它在做什么以及如何调整高度。

editor.getSession().getDocument().getLength() *
editor.renderer.lineHeight + editor.renderer.scrollBar.getWidth()
9个回答

105

(更新:目前我不再使用这个,但我的答案可能已经过时。为了尝试融合其他人提供的内容,我会引用他们提到的minLines和maxLines属性,例如:

editor.setOptions({
    maxLines: Infinity
});

显然,无限大并不是一个很好的选择,因为即使对于非常大的文档,它也会禁用虚拟视口,所以选择一个限制可能更好。

出于历史的原因,旧答案如下:


你引用的帖子只是假设它是一个定宽字体,你知道字符高度,以及你知道文档中行数。将它们相乘,你就得到了内容高度的像素计数。建议的方法是每次按下字符或发生剪切/粘贴(可能会添加或删除行)时,使用JavaScript将这个具体的新大小应用于DOM中带有CSS样式的项。

(他们将滚动条的“宽度”纳入高度计算中,我实在无法告诉你是否有理由这样做。我会让别人解决这部分问题。)

总之...如果你打开了自动换行功能,则跨越的屏幕行数可能比文档中的“实际”行数多。因此最好使用editor.getSession().getScreenLength()而不是editor.getSession().getDocument().getLength()

我将编辑器(position: absolute)放在一个区域(position: relative)内,它是该区域中唯一的项目。目前,这段代码对我来说似乎是有效的,如果我了解更多,我会更新它...!

$(document).ready(function(){

    var heightUpdateFunction = function() {

        // https://dev59.com/h2gu5IYBdhLWcg3wGTWd
        var newHeight =
                  editor.getSession().getScreenLength()
                  * editor.renderer.lineHeight
                  + editor.renderer.scrollBar.getWidth();

        $('#editor').height(newHeight.toString() + "px");
        $('#editor-section').height(newHeight.toString() + "px");

        // This call is required for the editor to fix all of
        // its inner structure for adapting to a change in size
        editor.resize();
    };

    // Set initial size to match initial content
    heightUpdateFunction();

    // Whenever a change happens inside the ACE editor, update
    // the size again
    editor.getSession().on('change', heightUpdateFunction);
}

1
添加了一个测试来检测水平滚动条的存在:var newHeight = editor.getSession().getScreenLength() * editor.renderer.lineHeight + (editor.renderer.$horizScroll ? editor.renderer.scrollBar.getWidth() : 0); - Amit Portnoy
Ace现在提供了maxLines选项,如另一个答案所述,它的效果要好得多。此外,从更改侦听器修改dom是一个坏主意,它会大大减慢编辑器的速度。 - a user
1
@auser 感谢您的反馈,我现在没有使用Ace,但如果这些选项可行,那么我会相信您的话...直到有人说它们不起作用。 :-) - HostileFork says dont trust SE
设置此选项后,初始高度将不是CSS中的值,而是根据内容的高度进行调整。但我仍想设置固定的初始高度,该怎么办? - soulmachine
1
我已经想通了,只需使用 editor.setOptions({minLines: 25}); 来设置最小行数为25。 - soulmachine

35

这并没有回答问题。问题是如何根据显示的行数设置高度。您建议使用硬编码值。 - Chris Peters
9
答案正确,您的评论是错误的。 Ace提供了maxLinesminLines选项,并将根据编辑器中有多少行自动设置高度在这些值之间。您还可以设置maxLines: Infinity,但这并不是一个很好的想法,因为它会即使对于非常大的文档也禁用虚拟视口。 - a user
你是第一个提到maxLines的人,所以你得到了我的点赞。 - Ciro Santilli OurBigBook.com
1
有没有办法让高度包括水平滚动条(如果存在)?在您的js fiddle中,将第12行更改为:“d djlkf kdfjlsk fdjkl dfjkls fkdjlksdf jkdf”,则会出现水平和垂直滚动条。如果高度调整,使得不需要垂直滚动条,那就太好了。 - Jereme
实际上,您可以调用 var lines = editor.getSession().getDocument().getLength() 然后将 maxLines 设置为该值。 - cayhorstmann

13
更新:请参考Dickeylth的答案。这一切仍然有效(人们似乎仍然觉得它有用),但是基本功能现在内置在ACE中。
要“自动调整Ace Cloud9编辑器中内容的高度”,只需要在编辑内容时将编辑器大小调整到适合包含它的div即可。假设您从<div id=editor>开始...
var editor = ace.edit("editor");                   // the editor object
var editorDiv = document.getElementById("editor");     // its container
var doc = editor.getSession().getDocument();  // a reference to the doc

editor.on("change", function() {
    var lineHeight = editor.renderer.lineHeight;
    editorDiv.style.height = lineHeight * doc.getLength() + "px";
    editor.resize();
});

你调整编辑器所在的 div 的大小,然后调用 editor.resize 方法来填充该 div。

如果你复制的内容包含长行,并且 ACE 设置为自动换行,则新行数和实际渲染行数将不同,因此编辑器将发生滚动。这段代码将解决这个问题,但是你将会出现水平滚动。

editor.getSession().setUseWrapMode(false)

1
你不能假设行高为16像素。相反,它可以从API中检索到。编辑答案以反映这一点。 - Xavi Montero
1
通常在实践中你会知道高度,所以我只是假设你知道它是16像素,但你的改进仍然是对硬编码的改进。不错。+1 - Carl Smith

9
我认为一个解决方案可能是计算编辑器中的行数,然后调整大小以适应这些行:
editor.setOptions({
     maxLines: editor.session.getLength()
});

希望这能有所帮助。

在我看来,maxLines: Infinity 在功能上做的事情似乎是一样的。在我的情况下,我将编辑器放在一个高度和宽度都设置为100%的容器div中。 - bildungsroman

2
您可以使用jQuery:
 var length_editor = editor.session.getLength();
 var rows_editor = length_editor * 17;

 $('#editor').css('height',rows_editor);

1
除了我更喜欢editor.getSession().getScreenLength()之外,我同意被接受的答案。 问题在于,如果启用换行模式,一行长文本可能会分成多行,因此你将无法通过editor.getSession().getDocument().getLength()获取正确的行数。

0

我曾经遇到过同样的问题,但后来发现只需通过获取其父元素的高度并将其赋给#editor,然后通过editor.resize()触发调整大小即可。它就像魔法一样奏效了!下面是我使用的代码:

let editor = ace.edit('editor'), $editorWrapper = $('.editor-wrapper');

$('#editor').height($editorWrapper.height());
 editor.resize();

嗯,我在尝试切换编辑器的最大化功能时做了这个。


0

我的方法是使用纯JavaScript(将editor-container替换为正确的id)。

function adaptEditor() {
    document.getElementById('editor-container').style.height = window.innerHeight + 'px';
    editor.resize();
}
window.onresize = function(event) {
    adaptEditor();
};
adaptEditor();

0

这个变量对我来说更好,因为有时候editor.renderer.lineHeight返回1

    var resize = function() {
     var minHt = 16;
     var sl = editor.getSession().getScreenLength();
     var sw = editor.renderer.scrollBar.getWidth();
     var lh = Math.max(editor.renderer.lineHeight, minHt);
     var ht = Math.max(((sl * lh) + sw), minHt);
     $('#myEditorDiv').height(ht);
     editor.resize();
   };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接