Prototype을 사용하여 텍스트 영역의 크기를 자동으로 조정하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/7477

문제

저는 현재 제가 일하는 회사의 내부 판매 신청서를 작성하고 있는데, 사용자가 배송 주소를 변경할 수 있는 양식을 가지고 있습니다.

이제 기본 주소 세부 정보에 사용하는 텍스트 영역이 텍스트 영역만 차지하고 텍스트가 변경되면 자동으로 크기가 조정된다면 훨씬 더 멋져 보일 것이라고 생각합니다.

현재 스크린샷은 다음과 같습니다.

ISO Address

어떤 아이디어가 있나요?


@크리스

좋은 지적이지만 크기를 조정하고 싶은 이유가 있습니다.나는 그것이 차지하는 영역이 그 안에 포함된 정보의 영역이기를 원합니다.스크린샷에서 볼 수 있듯이 고정된 텍스트 영역이 있으면 수직 공간이 꽤 많이 차지합니다.

글꼴을 줄일 수 있지만 크고 읽기 쉬운 주소가 필요합니다.이제 텍스트 영역의 크기를 줄일 수 있지만 주소 줄이 3~4줄(1줄은 5줄)인 사람들에게는 문제가 있습니다.사용자가 스크롤바를 사용하도록 하는 것은 절대 금물입니다.

좀 더 구체적으로 말씀드려야 할 것 같습니다.세로 크기를 조정한 후 너비가 그다지 중요하지 않습니다.여기서 발생하는 유일한 문제는 창 너비가 너무 작을 때(스크린샷에서 볼 수 있듯이) ISO 번호(큰 "1")가 주소 아래로 밀려나는 것입니다.

속임수를 쓰는 것이 아닙니다.불필요한 공간을 차지하지 않고 그 안의 모든 텍스트를 표시하는 사용자가 편집할 수 있는 텍스트 필드를 갖는 것입니다.

누군가가 문제에 접근하는 다른 방법을 생각해낸다면 나도 그것에 대해 열려 있습니다.


코드가 좀 이상해서 조금 수정했습니다.방금 입력한 문자를 고려하지 않기 때문에 키업 시 활성화되도록 변경했습니다.

resizeIt = function() {
  var str = $('iso_address').value;
  var cols = $('iso_address').cols;
  var linecount = 0;

  $A(str.split("\n")).each(function(l) {
    linecount += 1 + Math.floor(l.length / cols); // Take into account long lines
  })

  $('iso_address').rows = linecount;
};
도움이 되었습니까?

해결책

Facebook에서는 사람들의 담벼락에 글을 쓸 때 이를 수행하지만 크기는 수직으로만 조정됩니다.

가로 크기 조정은 단어 줄 바꿈, 긴 줄 등으로 인해 혼란스러워 보이지만 세로 크기 조정은 꽤 안전하고 좋은 것 같습니다.

내가 아는 페이스북 초보자 중 누구도 이에 대해 언급하거나 혼란스러워한 적이 없습니다.나는 이것을 '계속해서 구현하라'고 말하는 일화적인 증거로 사용하고 싶습니다.

이를 수행하는 일부 JavaScript 코드는 다음을 사용합니다. 원기 (왜냐하면 내가 아는 내용이니까):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script src="http://www.google.com/jsapi"></script>
        <script language="javascript">
            google.load('prototype', '1.6.0.2');
        </script>
    </head>

    <body>
        <textarea id="text-area" rows="1" cols="50"></textarea>

        <script type="text/javascript" language="javascript">
            resizeIt = function() {
              var str = $('text-area').value;
              var cols = $('text-area').cols;

              var linecount = 0;
              $A(str.split("\n")).each( function(l) {
                  linecount += Math.ceil( l.length / cols ); // Take into account long lines
              })
              $('text-area').rows = linecount + 1;
            };

            // You could attach to keyUp, etc. if keydown doesn't work
            Event.observe('text-area', 'keydown', resizeIt );

            resizeIt(); //Initial on load
        </script>
    </body>
</html>

추신:분명히 이 JavaScript 코드는 매우 순진하고 잘 테스트되지 않았으므로 소설이 들어 있는 텍스트 상자에 사용하고 싶지 않을 수도 있지만 일반적인 아이디어는 얻을 수 있습니다.

다른 팁

이러한 답변 중 일부를 개선한 것 중 하나는 CSS가 더 많은 작업을 수행하도록 하는 것입니다.

기본 경로는 다음과 같습니다.

  1. 컨테이너 요소를 생성하여 textarea 그리고 숨겨진 div
  2. Javascript를 사용하여 textarea의 콘텐츠가 div'에스
  3. 브라우저가 해당 div의 높이를 계산하도록 하세요.
  4. 브라우저가 숨겨진 렌더링/크기 조정을 처리하기 때문에 div, 우리는 명시 적으로 설정하지 않습니다 textarea의 키.

document.addEventListener('DOMContentLoaded', () => {
    textArea.addEventListener('change', autosize, false)
    textArea.addEventListener('keydown', autosize, false)
    textArea.addEventListener('keyup', autosize, false)
    autosize()
}, false)

function autosize() {
    // Copy textarea contents to div browser will calculate correct height
    // of copy, which will make overall container taller, which will make
    // textarea taller.
    textCopy.innerHTML = textArea.value.replace(/\n/g, '<br/>')
}
html, body, textarea {
    font-family: sans-serif;
    font-size: 14px;
}

.textarea-container {
    position: relative;
}

.textarea-container > div, .textarea-container > textarea {
    word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
    box-sizing: border-box;
    padding: 2px;
    width: 100%;
}

.textarea-container > textarea {
    overflow: hidden;
    position: absolute;
    height: 100%;
}

.textarea-container > div {
    padding-bottom: 1.5em; /* A bit more than one additional line of text. */ 
    visibility: hidden;
    width: 100%;
}
<div class="textarea-container">
    <textarea id="textArea"></textarea>
    <div id="textCopy"></div>
</div>

텍스트 영역의 크기를 자동으로 조정하는 또 다른 기술은 다음과 같습니다.

  • 줄 높이 대신 픽셀 높이를 사용합니다.비례 글꼴을 사용하는 경우 줄 바꿈을 더 정확하게 처리할 수 있습니다.
  • ID 또는 요소를 입력으로 허용합니다.
  • 선택적 최대 높이 매개변수를 허용합니다. 텍스트 영역이 특정 크기를 초과하지 않도록 하려는 경우에 유용합니다(모든 내용을 화면에 표시하고 레이아웃이 깨지지 않도록 하는 등).
  • Firefox 3에서 테스트되었으며 인터넷 익스플로러 6

암호:(일반 바닐라 JavaScript)

function FitToContent(id, maxHeight)
{
   var text = id && id.style ? id : document.getElementById(id);
   if (!text)
      return;

   /* Accounts for rows being deleted, pixel value may need adjusting */
   if (text.clientHeight == text.scrollHeight) {
      text.style.height = "30px";
   }

   var adjustedHeight = text.clientHeight;
   if (!maxHeight || maxHeight > adjustedHeight)
   {
      adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
      if (maxHeight)
         adjustedHeight = Math.min(maxHeight, adjustedHeight);
      if (adjustedHeight > text.clientHeight)
         text.style.height = adjustedHeight + "px";
   }
}

데모:(jQuery를 사용하여 지금 내가 입력하고 있는 텍스트 영역을 대상으로 합니다. 개똥 벌레 설치한 후 두 샘플을 모두 콘솔에 붙여넣고 이 페이지에서 테스트하세요)

$("#post-text").keyup(function()
{
   FitToContent(this, document.documentElement.clientHeight)
});

아마도 가장 짧은 해결책은 다음과 같습니다.

jQuery(document).ready(function(){
    jQuery("#textArea").on("keydown keyup", function(){
        this.style.height = "1px";
        this.style.height = (this.scrollHeight) + "px"; 
    });
});

이렇게 하면 숨겨진 div나 이와 유사한 것이 필요하지 않습니다.

메모:너랑 놀아야 할 수도 있어 this.style.height = (this.scrollHeight) + "px"; 텍스트 영역의 스타일을 지정하는 방법(줄 높이, 패딩 등)에 따라 다릅니다.

여기 원기 텍스트 영역의 열 수에 의존하지 않는 텍스트 영역 크기 조정 버전.이는 CSS를 통해 텍스트 영역을 제어할 수 있을 뿐만 아니라 가변 너비 텍스트 영역을 가질 수 있기 때문에 뛰어난 기술입니다.또한 이 버전에서는 남은 문자 수가 표시됩니다.요청되지는 않았지만 매우 유용한 기능이며 원치 않는 경우 쉽게 제거할 수 있습니다.

//inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
if (window.Widget == undefined) window.Widget = {}; 

Widget.Textarea = Class.create({
  initialize: function(textarea, options)
  {
    this.textarea = $(textarea);
    this.options = $H({
      'min_height' : 30,
      'max_length' : 400
    }).update(options);

    this.textarea.observe('keyup', this.refresh.bind(this));

    this._shadow = new Element('div').setStyle({
      lineHeight : this.textarea.getStyle('lineHeight'),
      fontSize : this.textarea.getStyle('fontSize'),
      fontFamily : this.textarea.getStyle('fontFamily'),
      position : 'absolute',
      top: '-10000px',
      left: '-10000px',
      width: this.textarea.getWidth() + 'px'
    });
    this.textarea.insert({ after: this._shadow });

    this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
    this.textarea.insert({after: this._remainingCharacters});  
    this.refresh();  
  },

  refresh: function()
  { 
    this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
    this.textarea.setStyle({
      height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
    });

    var remaining = this.options.get('max_length') - $F(this.textarea).length;
    this._remainingCharacters.update(Math.abs(remaining)  + ' characters ' + (remaining > 0 ? 'remaining' : 'over the limit'));
  }
});

호출하여 위젯 만들기 new Widget.Textarea('element_id').기본 옵션은 객체로 전달하여 재정의할 수 있습니다. new Widget.Textarea('element_id', { max_length: 600, min_height: 50}).페이지의 모든 텍스트 영역에 대해 생성하려면 다음과 같이 하십시오.

Event.observe(window, 'load', function() {
  $$('textarea').each(function(textarea) {
    new Widget.Textarea(textarea);
  });   
});

여기에 해결책이 있습니다. JQuery:

$(document).ready(function() {
    var $abc = $("#abc");
    $abc.css("height", $abc.attr("scrollHeight"));
})

abcteaxtarea.

아래 링크를 확인하세요:http://james.padolsey.com/javascript/jquery-plugin-autoresize/

$(document).ready(function () {
    $('.ExpandableTextCSS').autoResize({
        // On resize:
        onResize: function () {
            $(this).css({ opacity: 0.8 });
        },
        // After resize:
        animateCallback: function () {
            $(this).css({ opacity: 1 });
        },
        // Quite slow animation:
        animateDuration: 300,
        // More extra space:
        extraSpace:20,
        //Textarea height limit
        limit:10
    });
});

이것을 다시 살펴보니 조금 더 깔끔하게 만들었습니다(물병을 가득 채운 사람은 원기/JavaScript에서 개선 사항을 제안할 수 있습니까?).

var TextAreaResize = Class.create();
TextAreaResize.prototype = {
  initialize: function(element, options) {
    element = $(element);
    this.element = element;

    this.options = Object.extend(
      {},
      options || {});

    Event.observe(this.element, 'keyup',
      this.onKeyUp.bindAsEventListener(this));
    this.onKeyUp();
  },

  onKeyUp: function() {
    // We need this variable because "this" changes in the scope of the
    // function below.
    var cols = this.element.cols;

    var linecount = 0;
    $A(this.element.value.split("\n")).each(function(l) {
      // We take long lines into account via the cols divide.
      linecount += 1 + Math.floor(l.length / cols);
    })

    this.element.rows = linecount;
  }
}

그냥 다음과 같이 호출하세요:

new TextAreaResize('textarea_id_name_here');

나는 아주 쉬운 것을 만들었습니다.먼저 TextArea를 DIV에 넣었습니다.둘째, 나는 전화를 걸었습니다. ready 이 스크립트에 함수를 추가합니다.

<div id="divTable">
  <textarea ID="txt" Rows="1" TextMode="MultiLine" />
</div>

$(document).ready(function () {
  var heightTextArea = $('#txt').height();
  var divTable = document.getElementById('divTable');
  $('#txt').attr('rows', parseInt(parseInt(divTable .style.height) / parseInt(altoFila)));
});

단순한.렌더링된 div의 최대 높이를 한 행의 한 TextArea 높이로 나눈 값입니다.

나 자신을 위해 이 기능이 필요했지만 여기에 있는 기능 중 어느 것도 내가 필요로 하는 대로 작동하지 않았습니다.

그래서 오리온의 코드를 사용해서 바꿔봤습니다.

파괴할 때 너무 작아지지 않도록 최소 높이를 추가했습니다.

function resizeIt( id, maxHeight, minHeight ) {
    var text = id && id.style ? id : document.getElementById(id);
    var str = text.value;
    var cols = text.cols;
    var linecount = 0;
    var arStr = str.split( "\n" );
    $(arStr).each(function(s) {
        linecount = linecount + 1 + Math.floor(arStr[s].length / cols); // take into account long lines
    });
    linecount++;
    linecount = Math.max(minHeight, linecount);
    linecount = Math.min(maxHeight, linecount);
    text.rows = linecount;
};

@memical의 답변처럼요.

그러나 몇 가지 개선 사항을 찾았습니다.jQuery를 사용할 수 있습니다 height() 기능.그러나 패딩 상단 및 패딩 하단 픽셀에 유의하세요.그렇지 않으면 텍스트 영역이 너무 빨리 커질 것입니다.

$(document).ready(function() {
  $textarea = $("#my-textarea");

  // There is some diff between scrollheight and height:
  //    padding-top and padding-bottom
  var diff = $textarea.prop("scrollHeight") - $textarea.height();
  $textarea.live("keyup", function() {
    var height = $textarea.prop("scrollHeight") - diff;
    $textarea.height(height);
  });
});

jQuery를 사용하지 않는 내 솔루션(때로는 동일할 필요가 없기 때문에)은 다음과 같습니다.에서만 테스트되었지만 인터넷 익스플로러 7, 커뮤니티에서는 이것이 잘못된 모든 이유를 지적할 수 있습니다.

textarea.onkeyup = function () { this.style.height = this.scrollHeight + 'px'; }

지금까지는 이것이 작동하는 방식이 정말 마음에 들고 다른 브라우저에는 관심이 없으므로 아마도 모든 텍스트 영역에 적용할 것입니다.

// Make all textareas auto-resize vertically
var textareas = document.getElementsByTagName('textarea');

for (i = 0; i<textareas.length; i++)
{
    // Retain textarea's starting height as its minimum height
    textareas[i].minHeight = textareas[i].offsetHeight;

    textareas[i].onkeyup = function () {
        this.style.height = Math.max(this.scrollHeight, this.minHeight) + 'px';
    }
    textareas[i].onkeyup(); // Trigger once to set initial height
}

다음은 Jeremy가 6월 4일에 게시한 Prototype 위젯의 확장입니다.

텍스트 영역에서 제한을 사용하는 경우 사용자가 더 많은 문자를 입력하는 것을 중지합니다.남은 문자가 있는지 확인합니다.사용자가 텍스트를 텍스트 영역에 복사하면 텍스트가 최대로 잘립니다.길이:

/**
 * Prototype Widget: Textarea
 * Automatically resizes a textarea and displays the number of remaining chars
 * 
 * From: http://stackoverflow.com/questions/7477/autosizing-textarea
 * Inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
 */
if (window.Widget == undefined) window.Widget = {}; 

Widget.Textarea = Class.create({
  initialize: function(textarea, options){
    this.textarea = $(textarea);
    this.options = $H({
      'min_height' : 30,
      'max_length' : 400
    }).update(options);

    this.textarea.observe('keyup', this.refresh.bind(this));

    this._shadow = new Element('div').setStyle({
      lineHeight : this.textarea.getStyle('lineHeight'),
      fontSize : this.textarea.getStyle('fontSize'),
      fontFamily : this.textarea.getStyle('fontFamily'),
      position : 'absolute',
      top: '-10000px',
      left: '-10000px',
      width: this.textarea.getWidth() + 'px'
    });
    this.textarea.insert({ after: this._shadow });

    this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
    this.textarea.insert({after: this._remainingCharacters});  
    this.refresh();  
  },

  refresh: function(){ 
    this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
    this.textarea.setStyle({
      height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
    });

    // Keep the text/character count inside the limits:
    if($F(this.textarea).length > this.options.get('max_length')){
      text = $F(this.textarea).substring(0, this.options.get('max_length'));
        this.textarea.value = text;
        return false;
    }

    var remaining = this.options.get('max_length') - $F(this.textarea).length;
    this._remainingCharacters.update(Math.abs(remaining)  + ' characters remaining'));
  }
});

@memical jQuery를 사용하여 페이지 로드 시 텍스트 영역의 높이를 설정하는 멋진 솔루션이 있었지만 내 애플리케이션에서는 사용자가 더 많은 콘텐츠를 추가함에 따라 텍스트 영역의 높이를 늘릴 수 있기를 원했습니다.나는 다음을 사용하여 memical의 솔루션을 구축했습니다.

$(document).ready(function() {
    var $textarea = $("p.body textarea");
    $textarea.css("height", ($textarea.attr("scrollHeight") + 20));
    $textarea.keyup(function(){
        var current_height = $textarea.css("height").replace("px", "")*1;
        if (current_height + 5 <= $textarea.attr("scrollHeight")) {
            $textarea.css("height", ($textarea.attr("scrollHeight") + 20));
        }
    });
});

매우 부드럽지는 않지만 클라이언트 측 애플리케이션도 아니므로 부드러움은 실제로 중요하지 않습니다.(이것이 클라이언트 측이었다면 아마도 자동 크기 조정 jQuery 플러그인을 사용했을 것입니다.)

IE용으로 코딩하고 이 문제에 직면한 사람들을 위한 것입니다.IE에는 100% CSS로 만드는 약간의 트릭이 있습니다.

<TEXTAREA style="overflow: visible;" cols="100" ....></TEXTAREA>

IE에서는 무시하지만 다른 브라우저에서는 사용하게 될rows="n" 값을 제공할 수도 있습니다.나는 IE 핵을 구현하는 코딩을 정말 싫어하지만 이것은 매우 도움이 됩니다.Quirks 모드에서만 작동할 수도 있습니다.

인터넷 익스플로러, 사파리, 크롬 및 오페라 사용자는 CSS에서 line-height 값을 명시적으로 설정해야 합니다.다음과 같이 모든 텍스트 상자의 초기 속성을 설정하는 스타일시트를 작성합니다.

<style>
    TEXTAREA { line-height: 14px; font-size: 12px; font-family: arial }
</style>

여기에 제가 방금 jQuery로 작성한 함수가 있습니다. 이를 다음으로 포팅할 수 있습니다. 원기, 그러나 jQuery의 "활성"을 지원하지 않으므로 Ajax 요청으로 추가된 요소는 응답하지 않습니다.

이 버전은 확장될 뿐만 아니라 삭제 또는 백스페이스를 누르면 축소됩니다.

이 버전은 jQuery 1.4.2를 사용합니다.

즐기다 ;)

http://pastebin.com/SUKeBtnx

용법:

$("#sometextarea").textareacontrol();

또는 (예를 들어 jQuery 선택기)

$("textarea").textareacontrol();

그것은 테스트되었습니다 인터넷 익스플로러 7/인터넷 익스플로러 8, Firefox 3.5 및 Chrome.모두 잘 작동합니다.

ASP.NET을 사용하면 다음과 같이 하면 됩니다.

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Automatic Resize TextBox</title>
        <script type="text/javascript">
            function setHeight(txtarea) {
                txtarea.style.height = txtdesc.scrollHeight + "px";
            }
        </script>
    </head>

    <body>
        <form id="form1" runat="server">
            <asp:TextBox ID="txtarea" runat= "server" TextMode="MultiLine"  onkeyup="setHeight(this);" onkeydown="setHeight(this);" />
        </form>
    </body>
</html>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top