diff --git a/README.md b/README.md new file mode 100644 index 0000000..fa29e8b --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# BetterGrow: a jQuery plugin + +## Description + +Many things grow, but few grow better when they BetterGrow. + +BetterGrow is a customizable jQuery plugin for enabling the improved, dynamic expansion of a textarea. + +When the text within the target textarea exceeds the initial textarea height the textarea increases its height sufficiently to accommodate the new text. + +When the text within the target textarea decreases sufficient to allow for a lesser height, and the height is greater than the minimum textarea height or initial textarea height, then the textarea height is reduced to the minimum height required to display the text within while not obscuring the visibility or requiring a scrollbar to view any of the text. BetterGrow supports pre-existing text within the textarea. + +## Defaults +- initial textarea height is set to 26px (aka minimum textarea height) +- no event handling enabled + +## Implementation + + $('.textareas').BetterGrow(); + $('#textarea7, #textarea8').BetterGrow({ / * OPTIONS * / }); + +note: textarea MUST reside within an encapsulating / wrapping DIV to work + +## Compatibility + +- Tested in FF3.5, IE7 +- With jQuery 1.4 +- ** Width of textarea must be EXPLICITLY set to function normally in IE ** + +## Method(s) +When initialized the textarea object and its parent DIV have their attributes adjusted. + +The DIV should add no size to the textarea object or region. DIV height is automatically set to AUTO. + +The textarea's overflow is set to HIDDEN and the WIDTH is set to the current WIDTH. (i.e. WIDTH of textarea must be defined to work in IE) + +If the DIV is missing, the plugin will attempt to wrap the textarea in a new DIV. It is recommended that all targeted textareas are wrapped in a DIV before calling BetterGrow to avoid unexpected behavior. + +If the textarea already has text within it when BetterGrow is initialized the textarea's height is automatically adjusted to fit the text (if a height greater than the initial height is needed to present the text unobscured). + +## Customization + +BetterGrow(), i.e. + + $('.ta1').BetterGrow({initial_height:100px}); + +- initial_height: minimum height in pixels for the textarea, if the textarea is EMPTY, this is the initial height +- max_height: the maximum height, in pixels, that the textarea will grow, afterwhich it becomes overflow:auto; +- on_enter: callback function to call when ENTER is pressed within the target textarea(s) +- do_not_enter: if true, and on_enter is NOT NULL, then the ENTER event DOES NOT CASCADE / pass-through to the text area. if false, and on_enter is NOT NULL, then the ENTER event will trigger the calling of on_enter() and be reflected within the textarea (i.e. the textarea displays the submitted ENTER(S)) + +### EXAMPLE + OPTIONS = + { + initial_height: 50px, + on_enter: function() { submit_form(); }, + do_not_enter: false + }; + +## Get the skinny + +For more details about BetterGrow, its implementation, usage, and examples, go to the [BetterGrow](http://tpgblog.com/BetterGrow/) site. + +## Contributors + +[Jeremy Horn](http://tpgblog.com): original author +[Steven Harman](http://stevenharman.net): max_height option + +## Other + +dual licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php) and [GPL License](http://opensource.org/licenses/gpl-3.0.html) + +Copyright (c) 2009 Jeremy Horn- jeremydhorn(at)gmail(dot)c0m + diff --git a/bettergrow.demo.html b/bettergrow.demo.html index a5c303b..f8e1397 100644 --- a/bettergrow.demo.html +++ b/bettergrow.demo.html @@ -4,8 +4,8 @@ BetterGrow Plugin Demo - - + + + @@ -74,5 +76,14 @@ Area 8: missing DIV + Area 9: max-height of 150px + + Area 10: max-height of 150px, with more content + + diff --git a/bettergrow.min.demo.html b/bettergrow.min.demo.html index d2ca1f0..15cd779 100644 --- a/bettergrow.min.demo.html +++ b/bettergrow.min.demo.html @@ -4,8 +4,8 @@ BetterGrow Plugin Demo (Minimized) - - + + + @@ -74,5 +76,14 @@ Area 8: missing DIV + Area 9: max-height of 150px + + Area 10: max-height of 150px, with more content + + diff --git a/js/jquery.BetterGrow.js b/js/jquery.BetterGrow.js index 6bf60e9..866101f 100644 --- a/js/jquery.BetterGrow.js +++ b/js/jquery.BetterGrow.js @@ -69,12 +69,14 @@ initial_height: minimum height in pixels for the textarea if the textarea is EMPTY, this is the initial height + + max_height: the maximum height, in pixels, that the textarea will grow, afterwhich it becomes overflow:auto; on_enter: callback function to call when ENTER is pressed within the target textarea(s) do_not_enter: if true, and on_enter is NOT NULL, - then the ENTER event DOES NOT CASCADE / pass-through + then the ENTER event DOES NOT CASCADE / pass-through to the text area if false, and on_enter is NOT NULL, then the ENTER event will trigger the calling of @@ -124,7 +126,7 @@ // process all provided objects return this.each(function() { - var $this = $(this); + var $this = $(this); // wonder if people would prefer this or a setting that would conditionally wrap the div // @@ -132,7 +134,7 @@ if ($this.parent('div').length == 0) { $this.wrap('
'); } - + // reset textfield content // reset heights (these calls, right here, may be unnecessary -- brainstorm use cases set_height($this, c_settings.initial_height); @@ -163,8 +165,9 @@ **********************************************************************************/ $.fn.BetterGrow.settings = { initial_height: 26, // specified in pixels - on_enter: null, // callback function; if specified, this is called when enter is pressed - do_not_enter: true // if true and on_enter is not null then enter event does not cascade / pass-through to textarea + max_height: null, // specified in pixels + on_enter: null, // callback function; if specified, this is called when enter is pressed + do_not_enter: true // if true and on_enter is not null then enter event does not cascade / pass-through to textarea // no_div: true // if true, NEVER wrap the content in a div, but if div not present do nothing; if false, ALWAYS wrap in div -- maybe future RELEASE -- let's see feedback }; @@ -215,6 +218,7 @@ **********************************************************************************/ function make_better(the_object, settings) { var min_height = settings.initial_height; + var max_height = settings.max_height; // initialize parent DIV the_object.parent().css('height','auto'); @@ -228,7 +232,7 @@ // bind key events the_object.keydown( function(e) { - textarea_grow_some(the_object, min_height); + textarea_grow_some(the_object, min_height, max_height); if (e.keyCode == 13 /* ENTER */) { @@ -245,7 +249,7 @@ }); the_object.keyup ( function() { - textarea_grow_some(the_object, min_height) + textarea_grow_some(the_object, min_height, max_height) } ); /* important for catching ENTER */ } @@ -259,6 +263,9 @@ determine how to measure the height of the textarea [browser specific] determine whether or not the content of the text area is + > max_height, + THEN set to max_height + <= min_heigh, THEN set to min_height @@ -275,9 +282,9 @@ any associated textarea scrollbars **********************************************************************************/ - function textarea_grow_some(obj, min_height){ - var curr_height; - var curr_scroll_height; + function textarea_grow_some(obj, min_height, max_height){ + var curr_height, + curr_scroll_height; // do the math if (!textarea_grow_some.browser_calc){ @@ -285,30 +292,34 @@ textarea_grow_some.browser_calc = $.browser.msie || $.browser.safari; //does padding matter? + /* why not just use outerHeight() and let jQuery do this hard work? */ textarea_grow_some.padding_calc = textarea_grow_some.browser_calc ? ( parseInt(obj.css('padding-top')) + parseInt(obj.css('padding-bottom')) ) : 0; } - + curr_height = obj.height(); - + if (curr_height > min_height) { obj.parent().css('height', obj.height() + 'px' ); - + //set the height to zero to get the real content height obj.height(0); } - + curr_scroll_height = obj.get(0).scrollHeight - textarea_grow_some.padding_calc; // apply the math - if (curr_scroll_height > min_height) { - obj.height(curr_scroll_height); + if (max_height && (curr_scroll_height > max_height)) { + obj.height(max_height).css('overflow', 'auto'); + } + else if (curr_scroll_height > min_height) { + obj.css('overflow', 'hidden').height(curr_scroll_height); } else if (curr_height > min_height) { - obj.height(min_height); + obj.css('overflow', 'hidden').height(min_height); } - // restore initial height setting on parent DIV + // restore initial height setting on parent DIV obj.parent().css('height', 'auto'); } diff --git a/js/jquery.BetterGrow.min.js b/js/jquery.BetterGrow.min.js index a0141ee..fcfa531 100644 --- a/js/jquery.BetterGrow.min.js +++ b/js/jquery.BetterGrow.min.js @@ -1,3 +1,3 @@ /* jQuery.BetterGrow v 1.0 http://tpgblog.com/bettergrow/ compiled by http://yui.2clics.net/ */ -(function(b){b.fn.BetterGrow=function(e){var g;var f;if((typeof e=="object")||(e==undefined)){f=b.extend({},b.fn.BetterGrow.settings,e);return this.each(function(){var h=b(this);if(h.parent("div").length==0){h.wrap('
')}c(h,f.initial_height);d(h,f);h.keydown()})}return this};b.fn.BetterGrow.settings={initial_height:26,on_enter:null,do_not_enter:true};function c(f,e){f.height(e)}function d(f,g){var e=g.initial_height;f.parent().css("height","auto");f.css("overflow","hidden");f.unbind("keydown");f.unbind("keyup");f.keydown(function(h){a(f,e);if(h.keyCode==13){if(g.on_enter!=null){g.on_enter();if(g.do_not_enter){h.preventDefault();h.stopImmediatePropagation()}}}});f.keyup(function(){a(f,e)})}function a(h,f){var e;var g;if(!a.browser_calc){a.browser_calc=b.browser.msie||b.browser.safari;a.padding_calc=a.browser_calc?(parseInt(h.css("padding-top"))+parseInt(h.css("padding-bottom"))):0}e=h.height();if(e>f){h.parent().css("height",h.height()+"px");h.height(0)}g=h.get(0).scrollHeight-a.padding_calc;if(g>f){h.height(g)}else{if(e>f){h.height(f)}}h.parent().css("height","auto")}})(jQuery); \ No newline at end of file +(function($){$.fn.BetterGrow=function(options){var curr_this;var c_settings;if((typeof options=="object")||(options==undefined)){c_settings=$.extend({},$.fn.BetterGrow.settings,options);return this.each(function(){var $this=$(this);if($this.parent("div").length==0){$this.wrap('
');}set_height($this,c_settings.initial_height);make_better($this,c_settings);$this.keydown();});}return this;};$.fn.BetterGrow.settings={initial_height:26,max_height:null,on_enter:null,do_not_enter:true};function set_height(the_object,min_height){the_object.height(min_height);}function make_better(the_object,settings){var min_height=settings.initial_height;var max_height=settings.max_height;the_object.parent().css("height","auto");the_object.css("overflow","hidden");the_object.unbind("keydown");the_object.unbind("keyup");the_object.keydown(function(e){textarea_grow_some(the_object,min_height,max_height);if(e.keyCode==13){if(settings.on_enter!=null){settings.on_enter();if(settings.do_not_enter){e.preventDefault();e.stopImmediatePropagation();}}}});the_object.keyup(function(){textarea_grow_some(the_object,min_height,max_height);});}function textarea_grow_some(obj,min_height,max_height){var curr_height,curr_scroll_height;if(!textarea_grow_some.browser_calc){textarea_grow_some.browser_calc=$.browser.msie||$.browser.safari;textarea_grow_some.padding_calc=textarea_grow_some.browser_calc?(parseInt(obj.css("padding-top"))+parseInt(obj.css("padding-bottom"))):0;}curr_height=obj.height();if(curr_height>min_height){obj.parent().css("height",obj.height()+"px");obj.height(0);}curr_scroll_height=obj.get(0).scrollHeight-textarea_grow_some.padding_calc;if(max_height&&(curr_scroll_height>max_height)){obj.height(max_height).css("overflow","auto");}else{if(curr_scroll_height>min_height){obj.css("overflow","hidden").height(curr_scroll_height);}else{if(curr_height>min_height){obj.css("overflow","hidden").height(min_height);}}}obj.parent().css("height","auto");}})(jQuery);