Pregunta

Actualmente estoy trabajando en una aplicación de ventas interna para la empresa para la que trabajo y tengo un formulario que permite al usuario cambiar la dirección de entrega.

Ahora creo que se vería mucho mejor si el área de texto que estoy usando para los detalles de la dirección principal ocupara el área del texto y cambiara de tamaño automáticamente si se cambiara el texto.

Aquí hay una captura de pantalla actual.

ISO Address

¿Algunas ideas?


@cris

Un buen punto, pero hay razones por las que quiero cambiar su tamaño.Quiero que el área que ocupa sea el área de la información contenida en él.Como puede ver en la captura de pantalla, si tengo un área de texto fija, ocupa bastante espacio vertical.

Puedo reducir la fuente, pero necesito que la dirección sea grande y legible.Ahora puedo reducir el tamaño del área de texto, pero luego tengo problemas con las personas que tienen una línea de dirección que ocupa 3 o 4 (una toma 5) líneas.La necesidad de que el usuario utilice una barra de desplazamiento es un gran no-no.

Supongo que debería ser un poco más específico.Busco un cambio de tamaño vertical y el ancho no importa tanto.El único problema que ocurre con eso es que el número ISO (el "1" grande) aparece debajo de la dirección cuando el ancho de la ventana es demasiado pequeño (como puede ver en la captura de pantalla).

No se trata de tener un truco;se trata de tener un campo de texto que el usuario pueda editar y que no ocupe espacio innecesario, pero que muestre todo el texto que contiene.

Aunque si a alguien se le ocurre otra forma de abordar el problema, también estoy abierto a ello.


Modifiqué un poco el código porque actuaba un poco extraño.Lo cambié para activarlo al presionar una tecla, porque no tomaría en consideración el carácter que se acaba de escribir.

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;
};
¿Fue útil?

Solución

Facebook lo hace cuando escribes en los muros de las personas, pero solo cambia el tamaño verticalmente.

El cambio de tamaño horizontal me parece un desastre, debido al ajuste de palabras, las líneas largas, etc., pero el cambio de tamaño vertical parece ser bastante seguro y agradable.

Ninguno de los novatos que conozco en el uso de Facebook ha mencionado nunca nada al respecto ni se ha sentido confundido.Usaría esto como evidencia anecdótica para decir "adelante, impleméntelo".

Algún código JavaScript para hacerlo, usando Prototipo (porque eso es con lo que estoy familiarizado):

<!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>

PD:Obviamente, este código JavaScript es muy ingenuo y no está bien probado, y probablemente no quieras usarlo en cuadros de texto con novelas, pero ya tienes una idea general.

Otros consejos

Un refinamiento de algunas de estas respuestas es dejar que CSS haga más trabajo.

La ruta básica parece ser:

  1. Cree un elemento contenedor para contener el textarea y un escondido div
  2. Usando Javascript, mantenga el textareacontenidos sincronizados con el div's
  3. Deje que el navegador haga el trabajo de calcular la altura de ese div
  4. Porque el navegador se encarga de renderizar/dimensionar lo oculto div, evitamos establecer explícitamente el textareaLa altura.

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>

Aquí hay otra técnica para ajustar automáticamente el tamaño de un área de texto.

  • Utiliza altura de píxel en lugar de altura de línea:manejo más preciso del ajuste de línea si se utiliza una fuente proporcional.
  • Acepta ID o elemento como entrada
  • Acepta un parámetro de altura máxima opcional: útil si prefiere no permitir que el área de texto crezca más allá de un tamaño determinado (mantenerlo todo en pantalla, evitar romper el diseño, etc.)
  • Probado en Firefox 3 y Internet Explorer 6

Código:(JavaScript simple)

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

Manifestación:(usa jQuery, apunta al área de texto en la que estoy escribiendo ahora mismo, si tienes insecto de fuego instalado, pegue ambas muestras en la consola y pruebe en esta página)

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

Probablemente la solución más corta:

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

De esta manera no necesitas divs ocultos ni nada por el estilo.

Nota:tal vez tengas que jugar con this.style.height = (this.scrollHeight) + "px"; dependiendo de cómo le des estilo al área de texto (altura de línea, relleno y ese tipo de cosas).

Aquí está un Prototipo Versión para cambiar el tamaño de un área de texto que no depende del número de columnas en el área de texto.Esta es una técnica superior porque le permite controlar el área de texto a través de CSS y también tener un área de texto de ancho variable.Además, esta versión muestra la cantidad de caracteres restantes.Si bien no se solicita, es una característica bastante útil y se elimina fácilmente si no se desea.

//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'));
  }
});

Crea el widget llamando new Widget.Textarea('element_id').Las opciones predeterminadas se pueden anular pasándolas como un objeto, p. new Widget.Textarea('element_id', { max_length: 600, min_height: 50}).Si desea crearlo para todas las áreas de texto de la página, haga algo como:

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

Aquí hay una solución con JQuery:

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

abc es un teaxtarea.

Consulte el siguiente enlace: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
    });
});

Volviendo a visitar esto, lo he hecho un poco más ordenado (aunque alguien que tiene la botella llena Prototipo/JavaScript podría sugerir mejoras?).

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

Solo llama con:

new TextAreaResize('textarea_id_name_here');

He hecho algo bastante fácil.Primero puse TextArea en un DIV.En segundo lugar, he llamado a la ready función para este script.

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

Simple.Es la altura máxima del div una vez renderizado, dividida por la altura de un TextArea de una fila.

Necesitaba esta función para mí, pero ninguna de las de aquí funcionó como las necesitaba.

Entonces usé el código de Orion y lo cambié.

Agregué una altura mínima, para que en la destrucción no quede demasiado pequeña.

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

Me gusta la respuesta de @memical.

Sin embargo encontré algunas mejoras.Puedes usar jQuery height() función.Pero tenga en cuenta los píxeles de relleno superior e inferior.De lo contrario, su área de texto crecerá demasiado rápido.

$(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);
  });
});

Mi solución al no usar jQuery (porque a veces no tienen por qué ser lo mismo) se encuentra a continuación.Aunque sólo fue probado en Internet Explorer 7, para que la comunidad pueda señalar todas las razones por las que esto está mal:

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

Hasta ahora me gusta mucho cómo funciona y no me importan otros navegadores, así que probablemente lo aplicaré a todas mis áreas de texto:

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

Aquí hay una extensión del widget Prototipo que Jeremy publicó el 4 de junio:

Evita que el usuario ingrese más caracteres si usa límites en áreas de texto.Comprueba si quedan caracteres.Si el usuario copia texto en el área de texto, el texto se corta al máximo.longitud:

/**
 * 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 Tenía una solución increíble para configurar la altura del área de texto al cargar la página con jQuery, pero para mi aplicación quería poder aumentar la altura del área de texto a medida que el usuario agregaba más contenido.Construí a partir de la solución de memical con lo siguiente:

$(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));
        }
    });
});

No es muy fluido, pero tampoco es una aplicación orientada al cliente, por lo que la fluidez realmente no importa.(Si esto hubiera estado orientado al cliente, probablemente habría usado un complemento jQuery de cambio de tamaño automático).

Para aquellos que están codificando para IE y encuentran este problema.IE tiene un pequeño truco que lo convierte en 100% CSS.

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

Incluso puede proporcionar un valor para filas="n" que IE ignorará, pero que otros navegadores utilizarán.Realmente odio la codificación que implementa hacks de IE, pero este es muy útil.Es posible que sólo funcione en modo Quirks.

Internet Explorer, Safari, Chrome y Ópera los usuarios deben recordar establecer explícitamente el valor de altura de línea en CSS.Hago una hoja de estilo que establece las propiedades iniciales para todos los cuadros de texto de la siguiente manera.

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

Aquí hay una función que acabo de escribir en jQuery para hacerlo; puedes transferirla a Prototipo, pero no admiten la "vivacidad" de jQuery, por lo que los elementos agregados por solicitudes de Ajax no responderán.

Esta versión no sólo se expande, sino que también se contrae cuando se presiona eliminar o retroceder.

Esta versión se basa en jQuery 1.4.2.

Disfrutar ;)

http://pastebin.com/SUKeBtnx

Uso:

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

o (cualquier selector jQuery por ejemplo)

$("textarea").textareacontrol();

Fue probado en Internet Explorer 7/Internet Explorer 8, Firefox 3.5 y Chrome.Todo funciona bien.

Usando ASP.NET, simplemente haga esto:

<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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top