textarea模仿效果不佳。任何替换?

时间:2012-12-13 16:58:30

标签: javascript html css

我有这个html和css:http://jsfiddle.net/b7rDL/6/

HTML:

<div class="text-block" contenteditable="true" spellcheck="false">Some Text</div>

的CSS:

.text-block {
    resize: none;
    font-size:40px;
    border: none;
    line-height: 1;
    -moz-appearance: textfield-multiline;
    -webkit-appearance: textarea;
    min-width: 30px;
    overflow: visible;
    white-space: nowrap;
    display: inline-block;
}

此代码允许我编写没有宽度限制或高度限制的文本。它不显示滚动条,它随文本一起增长。这些基本上是我需要的功能。

  1. 如何将此转换为相同的常规textarea?我希望这可以在没有实现“contenteditable”的浏览器上工作。因此,我想用textarea或其他basiv元素替换div。我该怎么做? (我不介意使用JavaScript)。
  2. 如何禁用拼写检查程序? spellcheck=false不起作用。在这个例子中,当我专注于文本框时,我得到了那辆红色的红线。我正在使用Firefox。
  3. 当我专注时,如何摆脱边界? - 已解决
  4. 我不介意使用JavaScript来解决这些问题。

    对这些问题的任何答案都会对我有所帮助。

    由于

    更新:
    @Oylex帮我3个

7 个答案:

答案 0 :(得分:9)

#1

工作小提琴就在这里:http://jsfiddle.net/d9H9w/11/(在IE8,Chrome和Firefox中测试过)

您需要在用户在文本框中输入时设置宽度和高度属性。

高度

这非常简单:

  1. 获取textarea的内容
  2. 匹配换行符
  3. 在em中设置高度为换行符的总数(加上第一行为1,wiggle为1.5)。
  4. 在em中设置高度使得这个字体大小不可知,因此它可以使用多种字体大小。

    function getNewlines(){
        // get the value(text) of the textarea
        var content = textEl.value;
    
        //use regex to find all the newline characters
        var newLines = content.match(/\n/g);
    
        // use the count of newlines(+1 for the first line + 1 for a buffer)
        // to set the height of the textarea.
        textEl.style.height = ((newLines && newLines.length || 0)+2.5)+'em';
    };
    

    宽度

    这也很容易,只有一个问题。

    1. 获取textarea的内容
    2. 拆分换行符以获取由textarea
    3. 行组成的数组
    4. 排序以获得最长行
    5. 将宽度设置为em中最长字符串的长度,乘以约.6(我的代码中为emRatio),加上2 ems用于缓冲区空间。
    6. 最后一部分是踢球者。 'em'测量应该是一个正方形,表示单个角色占据的宽度和高度。这不考虑字距调整,因此字符的高度通常是准确的,但宽度取决于它周围的字符。因此,通过猜测和检查,我认为.6 em是关于字距调整后字符的平均宽度。 .6非常接近,所以我在宽度上加了2个ems来获得一点缓冲空间。

      var emRatio = .6;
      function longestLine(){
          // get the value(text) of the textarea
          var content = textEl.value;
      
          // split on newline's. this creates an array, where each item in
          // the array is the text of one line
          var a = content.split('\n');
      
          // use a sorting function to order the items in the array:
          // longest string to shortest string
          a.sort(function(a,b){return b.length - a.length});
      
          // use the longest string * the emRatio to set the width
          // Due to kerning, the letters aren't ever really 1em x 1em
          // So I'm multiplying by an approximate ratio here (guess and check)
          textEl.style.width = (a[0].length * emRatio + 2)+ 'em';
      };
      

      此实施的现有问题

      • 为了支持在长按键操作期间调整大小,还必须包含onkeydown处理程序(对于不包括长按键的所有情况,这不是最佳的)

      考虑到所有因素,我认为这符合您的需要。

      <强> EDITS

      不是将emRatio设为.7,而是将其更改为.6并在宽度上添加了2 ems的缓冲区。这解决了@Naor在评论中提到的两个问题。

      我已更新小提琴链接和宽度部分以反映更改。

答案 1 :(得分:4)

编辑0

请求#1更新

工作解决方案:http://jsfiddle.net/7aeU2/

JQuery的

$(function() {
    //  changes mouse cursor when highlighting loawer right of box
    $("textarea").mousemove(function(e) {
        var myPos = $(this).offset();
        myPos.bottom = $(this).offset().top + $(this).outerHeight();
        myPos.right = $(this).offset().left + $(this).outerWidth();

        if (myPos.bottom > e.pageY && e.pageY > myPos.bottom - 16 && myPos.right > e.pageX && e.pageX > myPos.right - 16) {
            $(this).css({ cursor: "nw-resize" });
        }
        else {
            $(this).css({ cursor: "" });
        }
    })
    //  the following simple make the textbox "Auto-Expand" as it is typed in
    .keyup(function(e) {
        //  the following will help the text expand as typing takes place
        while($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))) {
            $(this).height($(this).height()+1);
        };
    });
});​

请求#2更新

此外,这里有一个很好的解释,为什么你可以直接禁用拼写检查。

  

这不属于CSS领域(这是可选的   表达建议)。它不是关于风格的特征   渲染数据,但以交互方式处理数据。

     

在支持“拼写检查”的浏览器上(可能涉及语法)   和样式检查),HTML属性spellcheck或相应的   在JavaScript中可设置的IDL(DOM)属性是有效的。

     

在实践中,这些浏览器倾向于启用“拼写检查”   默认情况下仅适用于textareas,而textareas通常包含人类   语言文本,将其关闭听起来并不有用。它在任何一个   用户可控制的情况(用户可以关闭或选择   式语言)。

通过https://stackoverflow.com/a/9209791/1085891


请求#1

  1. 简单解决方案非常简单。

    工作示例:http://jsfiddle.net/b7rDL/12/

    JQuery的

    $("#Solution0").keyup(function(e) {   
        while($(this).outerHeight() < this.scrollHeight) {
            $(this).width($(this).width()+50);
        };
    });
    

    HTML

    <textarea id="Solution0" rows="1" style="height: 1.2em;"></textarea>
    
  2. Fancier解决方案,如果您需要,需要进行一些更新 宽度,而不是高度,以扩大。不过,它还不错。

  3. 其他解决方案 - 我知道这些都扩展了高度。如果您需要以下解决方案之一的宽度实现,请告诉我。

  4. 请求#2

    spellcheck="true"应该按照Mozilla docs: Controlling spell checking in HTML forms中的说明运作。它适用于我在Firefox 13.0.1中运行的第一个简单示例。你在运行什么版本?

答案 2 :(得分:3)

对于#3,您要查找的css选项是:outline: none;

答案 3 :(得分:2)

请求#2

工作Demo

<body spellcheck="false">
<div class="text-block" contenteditable="true">    
Some Text SpellCheck</div>

嗨Naor,这件事的唯一问题是它将禁用<body>标签中所有元素的 拼写检查 。如果你没关系那么你就可以使用它。

你的问题非常有趣,也很有挑战性。我希望这可以帮到你.. !!

答案 4 :(得分:2)

我无法弄清楚textarea内容的界限,所以我采用这种方法将textarea的内容复制成类似风格的p 1}}元素,设置为float: left;,然后根据textarea的大小调整p的大小。这可以处理宽度和高度。

我在Mac 10.8.1 FF 18.0,Safari 6.0,Chrome 25.0.1362.0 canary,iOS Safari 6.0.1和iOS Simulator 5.1(272.21)上进行了测试。我没有PC或IE便利。

http://jsfiddle.net/b7rDL/34/

HTML

<textarea id="tx" class="text-block" spellcheck="false"></textarea>
<p id="dupe" class="text-block"></p>

CSS

.text-block {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    resize: none;
    font-size:14px;
    border: none;
    line-height: 1;
    min-width: 30px;
    overflow: hidden;
    white-space: pre;
    display: block;
    outline: none;
    width: 30px;
    height: auto;
    border: 1px solid #ddd;
    background-color: #f7f7f7;
}

#dupe {
    float: left;
    display: none;
    width: auto;
    height: auto;
}

我添加了背景和边框,以便我可以看到正在发生的事情。

的JavaScript

// no `var` so they are global and easier to work
// with in the inspector when using jsFiddle

$tx = $('#tx');
$dupe = $('#dupe');
lineH = Number($tx.css('line-height').replace('px',''));

update();

$tx.on('keydown', function() {
    setTimeout(update, 0);
});
$tx.on('propertychange input keyup change', update);

function update() {
    $dupe.text($tx.val());
    $tx.css({
        width: $dupe.width() + 7,
        height: $dupe.height() + lineH
    });
}

// not sure if this is needed, leaving it because
// I don't have many browsers to test on
 $tx.on('scroll', function() {
     tx.scrollLeft = 0;
     tx.scrollTop = 0;
 });

我在右侧和底部添加了额外的空间,因为它似乎以这种方式执行更加一致。此外,在HTML中,wrap="off"对于Firefox版本是必需的,我正在使用。

我从this blog post获得了一些很好的提示。

答案 5 :(得分:0)

当我在过去非常接近的时候为我工作的最有效的方法是创建隐藏的流程div,其具有与textarea相同的完全样式。而不是根据textarea的信息设置更新其html源的超时。这听起来有点吓人但是,经过一些测试和玩游戏后没有什么比这更好了,这已经建议了,所以只是我的变种。

http://jsfiddle.net/f2gAD/16/

和基于jQuery的脚本:

var textarea = $('textarea'),
    textBlock = $('div.text-block'),
    interval, value, freq = 10,
    doTextAreaAdjust = function(){
       textarea.css({
          height: textBlock.outerHeight(),
          width: textBlock.outerWidth()
       });
    };
doTextAreaAdjust();
textarea
.focus(function(){
    interval = window.setInterval(
        function() {
          value = textarea.val().replace(/(\r\n|\n|\r)/gm, '[rnnr]');
          value = value.replace(/</gm, '||'); // break html tags
          value = value.replace(/\[rnnr\]/gm, '<br>');
          value = value + '|'; // or <span>|</span> for better pixel perfect
          textBlock.html(value);
          doTextAreaAdjust();
        }, freq
    );console.log(interval);
})
.blur(function(){
    window.clearInterval(interval);
});
​

对于性能明智的做法是将其作为焦点/模糊的自启动/停止超时,尽管这里还需要一些解决方法。虽然在Chrome中进行测试时发现,如果您通过单击其他选项卡进行模糊,则间隔未正确停止。因此,将{@ 1}}中的自我调用功能替换为更好。

它在IE 7-8中或多或少都有效,它假设主要目标但仍有一些文本不时跳跃,而对于其他人则没关系,但猜测你将使用现代浏览器的可编辑功能。建议使用现代化器进行检测。

答案 6 :(得分:-1)

在这里工作 http://jsfiddle.net/H2GSx/

此处的代码: HTML:

<div style="overflow: scroll; width: 200px; height: 100px;">
    <div class="text-block" contenteditable="true" spellcheck="false">Some Text</div>
</div>​

CSS:

.text-block {
    resize: none;
    font-size:40px;
    border: none;
    line-height: 1;
    -moz-appearance: textfield-multiline;
    -webkit-appearance: textarea;
    min-width: 30px;
    overflow: visible;
    white-space: nowrap;
    display: inline-block;
}
​