Previously i showed you how to create inline timepicker for Jeditable. This time we will create autogrowing textarea. This custom input will adjust its height while you type. Code uses excellent Autogrow jQuery plugin by Chrys Bader.

If this is your first encounter with Jeditable custom inputs you might want to read an introduction to them.

If you are just looking for the code download it here.

Creating custom input

Throughout the tutorial we will be using following code to trigger Jeditable.

$(".edit").editable("http://www.example.com/save.php", { 
    type      : "autogrow",
    submit    : 'OK',
    cancel    : 'Cancel',
    tooltip   : "Click to edit...",
    onblur    : "ignore",
    autogrow : {
        lineHeight : 16,
        maxHeight  : 512
    }
});

We start by adding custom input type called autogrow.

$.editable.addInputType('autogrow', {
});

At the moment code does not do much anything. Since no methods are defined plugin will call the default methods. It creates hidden input and submit button.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Add textarea element

Next we add the basic textarea element. This code is copied from the original textarea input. Initial size is set using rows and columns or pixel height and width. Nothing exiting here yet.

$.editable.addInputType('autogrow', {
    element : function(settings, original) {
        var textarea = $('<textarea>');
        if (settings.rows) {
            textarea.attr('rows', settings.rows);
        } else {
            textarea.height(settings.height);
        }
        if (settings.cols) {
            textarea.attr('cols', settings.cols);
        } else {
            textarea.width(settings.width);
        }
        $(this).append(textarea);
        return(textarea);
    }
});

Click text below to see how it works. Basic textarea is now created. Write lot of text and scrollbar appears.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Make it grow!

To make our textarea grow we attach Chrys’s Autogrow plugin to it. Note how we pass settings to it. Check Autogrow source to see all available options.

What does $(‘textarea’, this) selector do? Inside all addInputType() functions variable this refers to Jeditable form. In plain english selector means “textarea inside Jeditable form”.

$.editable.addInputType('autogrow', {
    element : function(settings, original) {
        ...
    },
    plugin : function(settings, original) {
        $('textarea', this).autogrow(settings.autogrow);
    }
});

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Thats it! Finished code is available for download. Do you have any custom input wishes? Have you coded one yourself? Leave a comment and let me know. For inspiration check custom inputs demo.


14 Responses to “Autogrow Textarea for Jeditable”

  1. Richard Davies says:

    This looks like a nice custom input type. I thought I’d share a couple of the custom input types that I’ve created. The first one is for checkboxes:

    // Create a custom input type for checkboxes
    $.editable.addInputType("checkbox", {
        element : function(settings, original) {
            var input = $('<input type="checkbox">');                
            $(this).append(input);
    
            // Update <input>'s value when clicked
            $(input).click(function() {
                var value = $(input).attr("checked") ? 'Yes' : 'No';
                $(input).val(value);
            });
            return(input);
        },
        content : function(string, settings, original) {
            var checked = string == "Yes" ? 1 : 0;
            var input = $(':input:first', this);
            $(input).attr("checked", checked);
            var value = $(input).attr("checked") ? 'Yes' : 'No';
            $(input).val(value);
        }
    });
    

    The second one is a bit more complex. It’s a date widget with three select boxes (for month, day, and year):

    // Create a custom input type for date fields
    $.editable.dateTypeCount = 0;
    $.editable.addInputType("date", {
        element : function(settings, original) {
            var param = {count: ++$.editable.dateTypeCount};
            var wrapper = $('<span>');
            var selectMonth = $('<select id="date{count}-mm" name="date-mm">'.supplant(param));                
            var selectDay = $('<select id="date{count}-dd" name="date-dd">'.supplant(param));                
            var selectYear = $('<select id="date{count}" name="date">'.supplant(param));                
            var defaultOption = $('<option value=""></option>');
    
            // Add month option values
            $(defaultOption).clone().appendTo(selectMonth);
            for (var i = 1; i <= 12; i++) {
                // Convert numeric month into 3 letter abbreviation (i.e. "Feb")
                var month = new Date(2000, i-1).toString().substr(4, 3);
                var param = {i: i, month: month};
                var option = $('<option value="{i}">{month}</option>'.supplant(param));
                $(selectMonth).append(option);
            }
    
            // Add day option values
            $(defaultOption).clone().appendTo(selectDay);
            for (var i = 1; i <= 31; i++) {
                var param = {i: i};
                var option = $('<option value="{i}">{i}</option>'.supplant(param));
                $(selectDay).append(option);
            }
    
            // Add year option values
            $(defaultOption).clone().appendTo(selectYear);
            var year = new Date().getFullYear();
            for (var i = year; i >= 1980 ; i--) {
                var param = {i: i};
                var option = $('<option value="{i}">{i}</option>'.supplant(param));
                $(selectYear).append(option);
            }
    
            // Put 'em all together
            $(wrapper).append(selectMonth).append(" ");
            $(wrapper).append(selectDay).append(" ");
            $(wrapper).append(selectYear);
            $(this).append(wrapper);
    
            // Create hidden input that will contain the value to be submitted
            var input = $('<input type="hidden">');                
            $(this).append(input);
            return(input);
        },
        content : function(string, settings, original) {
            // Set "selected" attribute of correct option
            var date = new Date(string);
            var param = {month: date.getMonth()+1, day: date.getDate(), year: date.getFullYear()};
            var monthOption = $('[name=date-mm] [value={month}]'.supplant(param), this);
            var dayOption = $('[name=date-dd] [value={day}]'.supplant(param), this);
            var yearOption = $('[name=date] [value={year}]'.supplant(param), this);
            $(monthOption).attr("selected", "selected");
            $(dayOption).attr("selected", "selected");
            $(yearOption).attr("selected", "selected");
        },
        submit : function(settings, original) {
            // Transfer date from selects to hidden input
            var selectMonth = $('[name=date-mm]', this);
            var selectDay = $('[name=date-dd]', this);
            var selectYear = $('[name=date]', this);
            var date = selectMonth.val() + "/" + selectDay.val() + "/" + selectYear.val();
            if (date == "//")
                date = "";
            $('input', this).val(date);
        }
    });
    

    And here’s the supplant() function used above to do variable substitution in strings:

    // Variable substitution function - http://javascript.crockford.com/remedial.html
    String.prototype.supplant = function (o) {
        return this.replace(/{([^{}]*)}/g,
            function (a, b) {
                var r = o[b];
                return typeof r === 'string' || typeof r === 'number' ? r : a;
            }
        );
    };
    
  2. Mika Tuupola says:

    Great stuff! Do you have the source available for download somewhere? If yes I would like to link straight there. If not do you mind if I copy your code into my svn and make it available to download from my site?

  3. Richard Davies says:

    I’ve uploaded the code to http://www.mediafire.com/?bmy0iqlwttc You’re free to add it to your SVN repository or use it as you’d like.

    I also have a suggestion for the plugin. I would like to see the tooltip removed when the inputs are displayed. Currently, the “click to edit” toolip is still displayed when you hover over the input or the buttons, which is confusing.

  4. Jacob Abshire says:

    After some testing, it looks like the Autogrow plugin cancels the loadurl where input content is fetched before edited. Any ideas on resolution?

  5. Jacob Abshire says:

    Sorry, it seems that the problem is due to the calling of jQuery.noConflict(); when using other APIs on the same page. :)

  6. Mika Tuupola says:

    Jacob : so I assume problem solved?

  7. M says:

    What about autogrowing a text input field, not just a textarea?

  8. Mark Snape says:

    Hi Mika I’m getting great results using jeditable – thanks.

    I have run into a bit of a usability issue. When the text area is activated, all the text is selected. If the user does not notice they can blast the lot with one keypress.

    On your normal demo, I notice that this is the case also, but on the Autogrow demo (and on this page also), clicking the text area places the cursor at the top with no text selected – which is what I want. I have implemented Autogrow but this behaviour has not changed. Any suggestions?

    I should just say that one difference of my tests compared to your sample is that the editable area is a div and not a para.

    Thanks if you can help…

  9. Barb says:

    Hi Richard,

    I’m using your checkbox plugin, it’s great thanks. Only one problem. I’m getting a very wide area around my checkbox when I click on it.

    Any idea why? Any advice would be greatly appreciated.

  10. Mark Snape says:

    Hi Mika Regarding my earlier question, I have found the problem. For some reason an option select:true had crept into my jeditable options!

    All good now… Thanks

  11. David Huffman says:

    Mike,

    Thanks for creating jeditable. I was trying to implement this and am receiving an error: $(“textarea”, this).autogrow is not a function. Any ideas?

  12. Mika Tuupola says:

    David: Are you including the Chrys Baders Autogrow plugin somewhere in the page? His download page seems to be down. But grab a copy from here.

  13. author says:

    is it just me or does the cancel button not seem to work?

  14. Mika Tuupola says:

    author: I just checked with another demopage with cancel button added. Worked ok with me. Do you have example page somewhere which shows the problem?

Leave a Reply



(will not be published)



(you can use Textile for formatting)