كيفية ضبط حجم منطقة النص تلقائيًا باستخدام النموذج الأولي؟

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

سؤال

أعمل حالياً على تطبيق مبيعات داخلية للشركة التي أعمل بها، ولدي نموذج يسمح للمستخدم بتغيير عنوان التسليم.

أعتقد الآن أن الأمر سيبدو أجمل بكثير، إذا كانت منطقة النص التي أستخدمها لتفاصيل العنوان الرئيسي ستشغل فقط مساحة النص الموجود فيها، ويتم تغيير حجمها تلقائيًا إذا تم تغيير النص.

وهنا لقطة من ذلك حاليا.

ISO Address

أيه أفكار؟


@ كريس

نقطة جيدة، ولكن هناك أسباب تجعلني أرغب في تغيير حجمها.أريد أن تكون المساحة التي يستغرقها الأمر هي مساحة المعلومات الموجودة فيه.كما ترون في لقطة الشاشة، إذا كان لدي منطقة نصية ثابتة، فإنها تشغل مساحة كبيرة من المساحة الرأسية.

يمكنني تصغير الخط، لكن أحتاج إلى أن يكون العنوان كبيرًا وسهل القراءة.يمكنني الآن تقليل حجم منطقة النص، ولكن بعد ذلك أواجه مشكلات مع الأشخاص الذين لديهم سطر عنوان يستغرق 3 أو 4 أسطر (يستغرق المرء 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. دع المتصفح يقوم بحساب ارتفاع هذا القسم
  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>

إليك أسلوبًا آخر لتغيير حجم منطقة النص تلقائيًا.

  • يستخدم ارتفاع البكسل بدلاً من ارتفاع الخط:معالجة أكثر دقة لالتفاف الخط في حالة استخدام خط متناسب.
  • يقبل إما المعرف أو العنصر كمدخل
  • يقبل معلمة الحد الأقصى للارتفاع الاختيارية - مفيدة إذا كنت تفضل عدم السماح لمنطقة النص بالنمو إلى ما هو أبعد من حجم معين (احتفظ بها كلها على الشاشة، وتجنب كسر التخطيط، وما إلى ذلك)
  • تم اختباره على Firefox 3 و إنترنت إكسبلورر 6

شفرة:(جافا سكريبت الفانيليا العادي)

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

abc هو teaxtarea.

تحقق من الرابط أدناه: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 بمجرد عرضه، مقسومًا على ارتفاع منطقة نص واحدة في صف واحد.

كنت بحاجة إلى هذه الوظيفة لنفسي، ولكن لم يعمل أي من الأشخاص هنا كما كنت أحتاج إليها.

لذلك استخدمت كود أوريون وقمت بتغييره.

لقد أضفت الحد الأدنى للارتفاع، بحيث لا يصبح صغيرًا جدًا عند التدمير.

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
}

فيما يلي امتداد لعنصر واجهة المستخدم النموذجي الذي نشره جيريمي في الرابع من يونيو:

فهو يمنع المستخدم من إدخال المزيد من الأحرف إذا كنت تستخدم حدودًا في مناطق النص.يتحقق مما إذا كانت هناك أحرف متبقية.إذا قام المستخدم بنسخ النص إلى منطقة النص، فسيتم قطع النص عند الحد الأقصى.طول:

/**
 * 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>

يمكنك أيضًا توفير قيمة للصفوف = "n" التي سيتجاهلها IE، لكن المتصفحات الأخرى ستستخدمها.أنا حقًا أكره البرمجة التي تنفذ اختراقات IE، ولكن هذا مفيد جدًا.من الممكن أنه يعمل فقط في وضع Quirks.

إنترنت إكسبلورر، سفاري، كروم و الأوبرا يحتاج المستخدمون إلى تذكر تعيين قيمة ارتفاع الخط بشكل واضح في CSS.أقوم بإنشاء ورقة أنماط تحدد الخصائص الأولية لجميع مربعات النص على النحو التالي.

<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, وفايرفوكس 3.5 وكروم.كل شيء يعمل بشكل جيد.

باستخدام 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