3

I would like to create HTML input fields (either single-line or textarea) that stop accepting new text when they are "full" - i.e. when there is no more room in the widget for new characters to be displayed.

This is different from a putting a maxlength limit on the number of characters, as (for example) 65 lowercase letter "i"s take up much less space than 65 uppercase "W"s in proportional fonts.

Is there a way to do this? (If there is, the solution would ideally also cover when text is pasted in, and truncate all the text over the limit).

Edit: The solution has to work with proportional fonts - maxlength does not help here, we are not interested in stopping at a character length.

adx
  • 41
  • 4
  • 3
    apply maxlenght attr to input filed – EnterJQ Feb 22 '13 at 12:33
  • @EnterJQ - Doesn't work for textarea. – Oded Feb 22 '13 at 12:35
  • Here's the answer: http://stackoverflow.com/questions/1752768/is-there-a-max-size-to-the-length-of-a-hidden-input-in-html – Glenn Ferrie Feb 22 '13 at 12:35
  • You could use a mono-spaced font together with `max-length`, but I assume you explicitly need a variable amount of characters in your input. – Sirko Feb 22 '13 at 12:35
  • What if the user has defined custom fonts and font sizes? What is the actual requirement? Why stop when the visible area is "full"? – Oded Feb 22 '13 at 12:36
  • http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript this might be sort of what your looking for (text input only, text area might work like this too but multi lines makes it a bit more difficult) – NickSlash Feb 22 '13 at 12:36
  • For an input you can certainly create an identical but auto-sized element off-screen, update its value on the fly and measure its width. If the width goes over that of the "real" input, you know no more text can be accepted (including that which placed you over the limit). For textarea... not sure. – Jon Feb 22 '13 at 12:37
  • possible duplicate of [Set maxlength in Html Textarea](http://stackoverflow.com/questions/4459610/set-maxlength-in-html-textarea) – Paul S. Feb 22 '13 at 12:42
  • @Oded the use case is complex, but imagine something like a mailing address label creator or business card editor, where the number of characters doesn't matter, but their actual size does. We can control the user font and sizes. – adx Feb 22 '13 at 12:54
  • @user2087687 - That's something you should be doing on the server side, not client side (and if you mean printing from the browser - even worse, as there is no guarantee that what's printed will match what's on screen). – Oded Feb 22 '13 at 12:58
  • @oded right, this isn't physically printing, but the needs are the same: we need to give users a tool that lets them do WYSIWYG editing of HTML output (in a tightly controlled input and output environment based on HTML). – adx Feb 22 '13 at 13:03

3 Answers3

1

The following uses the answer from https://stackoverflow.com/a/5047712/212869 to calculate the width of text, and I linked it to a textbox. Its really rough code :D but it does limit the textbox fairly well. The same principle could be used on a text area, but you would also have do it for both height and width.

http://jsfiddle.net/LMKtd/1/ - it outputs stuff to console so best to have it open if you have a look.

String.prototype.width = function(font) {
  var f = font || '12px arial',
      o = $('<div>' + this + '</div>')
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
            .appendTo($('body')),
      w = o.width();

  o.remove();

  return w;
}

$('#textinput').on('keyup', validatetext);

function validatetext(e) {
    var w = parseInt(e.target.value.width());
    if (w > 100) {
        console.log("Width Gt 100px ["+w+"px] Char Count ["+e.target.value.length+"]");
        do {
            e.target.value = e.target.value.slice(0,-1);
        } while (parseInt(e.target.value.width()) > 100)
    } else {
        console.log("Keep going! ["+w+"px] Char Count ["+e.target.value.length+"]");
    }
}

Update

http://jsfiddle.net/LMKtd/8/

I've bodged together one for the text area too. It doesnt stop you going over the limits but it tells you when its too wide or tall. It's not very pretty :D

String.prototype.width = function(font) {
  var f = font || '12px arial',
      o = $('<div>' + this + '</div>')
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'visible', 'font': f})
            .appendTo($('body')),
      w = o.width();
  o.remove();

  return w;
}

String.prototype.height = function(font) {
  var f = font || '12px arial',
      o = $('<div>' + this.replace(/[\r\n]/g,'<br />') + '</div>')
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
            .appendTo($('body')),
      w = o.height();
  o.remove();

  return w;
}

$('#textinput').on('keyup', validatetext);
$('#areainput').keyup(validatearea);

function validatearea(e) {
    var w = parseInt($(this).val().width());
    var h = parseInt($(this).val().height());
    var errw = false;
    var errh = false;
    if (h>100) {
        errh = true
    }
    var lines = $(this).val().split(/[\r\n]/);
    var errw = false;
    for (var i = 0; i<lines.length; i++) {
        if (parseInt(lines[i].width()) > 100) {
            errw = true;
        }
    }
    if ((errh == true) || (errw == true)) {
        if ((errh == true) && (errw == false)) {
            $('#areaerror').html("Too Tall, Width OK");        
        }
        if ((errh == false) && (errw == true)) {
            $('#areaerror').html("Height OK, Too Wide");        
        }
        if ((errh == true) && (errw == true)) {
            $('#areaerror').html("Too Tall, Too Wide");        
        }
    } else {
        $('#areaerror').html("Were Good");    
    }
}


function validatetext(e) {
    var w = parseInt(e.target.value.width());
    if (w > 100) {
        console.log("Width Gt 100px ["+w+"px] Char Count ["+e.target.value.length+"]");
        do {
            e.target.value = e.target.value.slice(0,-1);
        } while (parseInt(e.target.value.width()) > 100)
    } else {
        console.log("Keep going! ["+w+"px] Char Count ["+e.target.value.length+"]");
    }
}
Community
  • 1
  • 1
NickSlash
  • 4,758
  • 3
  • 21
  • 38
  • This looks like a great start, thanks Nick! I'm having trouble getting the limit on the input field to line up exactly with the field, but it's a really promising start. – adx Feb 22 '13 at 14:58
  • you will need to make sure the style used in the `height` and `width` functions matches that of your textarea as its currently defaulted to 12px arial (i didnt for my demo so its probably wrong there too) – NickSlash Feb 22 '13 at 15:33
0

You can use the maxlength attribute

<input type="text" id="Textbox" name="Textbox" maxlength="10" />
Jacob
  • 3,580
  • 22
  • 82
  • 146
  • 1
    Thanks but see the question - can't use maxlength as 10 "i"s take up less visible space than 10 "W"s – adx Feb 22 '13 at 12:49
0

How about jquery inputfit plugin ? check the demo and source

You might change the source to accommodate your requirements. Obviously you have to use jquery library an may not be suitable if you are searching for a solution in plain-JavaScript.

check the options (min size, max size) they seems fit for your requirement

sakhunzai
  • 13,900
  • 23
  • 98
  • 159