Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

textarea immitation is not working well. any replacements?

I have this html and 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;
}

This code allows me to write text with no width limit or height limit. It displays no scroll bar and it grows with the text. Those are basically the features I need.

  1. How can I convert this to regular textarea that will act the same? I want this to work on browser that doesn't implemented "contenteditable". Therefore I want to replace the div with textarea or other basiv element. How can I do it? (I don't mind using JavaScript).
  2. How can I disable the spellchecker? spellcheck=false doesn't work. In the example, when I focus on the text box, I get that buggy red line. I am using Firefox.
  3. How can I get rid of the border when I am focused? - SOLVED

I don't mind using JavaScript to solve those issues.

Any answer for those questions will help me.

Thanks

UPDATES:
@Oylex helped me with 3

like image 931
Naor Avatar asked Dec 13 '12 16:12

Naor


2 Answers

#1

Working fiddle is here: http://jsfiddle.net/d9H9w/11/ (tested in IE8, Chrome and Firefox)

What you need is to set the width and height attributes as a user is typing within a text box.

Height

This is pretty straightforward:

  1. Get the content of the textarea
  2. Match for newline characters
  3. Set the height to total number of newline characters(plus one for the first line and 1.5 for wiggle room) in em's.

Setting the height in em's makes this font-size agnostic, so it'll work with multiple font-sizes.

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

Width

This is fairly easy, too, with one gotcha.

  1. Get the content of the textarea
  2. Split on newline characters to get an array consisting of lines of the textarea
  3. Sort to get the longest line
  4. Set the width to the length of the longest string in em's, multiplied by about .6(emRatio in my code), plus 2 ems for buffer space.

That last part is the kicker. The 'em' measurement is supposed to be a square representing the width and height that a single character takes up. This doesn't take kerning into account, so the height of a char is usually accurate, but the width is dependent on the chars around it. So, by guess and check, I figured that .6 em is about the average width of a character after kerning. .6 is pretty close, so I add 2 ems to the width for a bit of buffer space.

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

Existing problems with this implementation

  • To support resizing during long-held key presses, an onkeydown handler has to be included as well(this is not optimal for all cases that don't include long key presses)

All things considered, I think this fits what you need.

EDITS

Instead of having emRatio be .7, I changed it to .6 and added a buffer of 2 ems to the width. This addresses both issues @Naor mentioned in his comments.

I've updated the fiddle link and the Width section to reflect the changes.

like image 77
freethejazz Avatar answered Nov 05 '22 01:11

freethejazz


EDIT 0

Request #1 Update

Working Solution: 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);
        };
    });
});​

Request #2 Update

Also, here's a good explanation of why you can't outright disable spell check.

This does not belong to the realm of CSS (which is optional presentational suggestions). It is not about stylistic features of rendering data but about processing data interactively.

On browsers that support “spell checking” (which may involve grammar and style checks), the HTML attribute spellcheck or the corresponding IDL (DOM) attribute, settable in JavaScript, is effective.

In practice, those browsers tend to have “spelling checking” enabled by default for textareas only, and as textareas normally contain human language texts, turning it off does not sound useful. It is in any case user-controllable (the user can switch it off or select language).

via https://stackoverflow.com/a/9209791/1085891


Request #1

  1. Simple Solution is pretty straight forward.

    Working example: 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 solution that will require some updating if you want the width, rather than the height, to expand. Still, it's pretty nice.

    • http://jsfiddle.net/edelman/HrnHb/
    • https://github.com/ultimatedelman/autogrow
  3. Other solutions - I know these all expand height. Let me know if you need width implementation of one of the below solutions.

    • http://bgrins.github.com/ExpandingTextareas/
    • http://blogs.sitepointstatic.com/examples/tech/textarea-expander/index.html
    • http://code.google.com/p/xautoresize-jquery/downloads/list
    • http://www.impressivewebs.com/textarea-auto-resize/
    • http://www.technoreply.com/autogrow-textarea-plugin-3-0/

Request #2

spellcheck="true" should work as described in the Mozilla docs: Controlling spell checking in HTML forms. It works for me in my first simple example running in Firefox 13.0.1. What version are you running?

like image 4
JSuar Avatar answered Nov 05 '22 01:11

JSuar