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.


6 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?

Leave a Reply