1/* 2 * jQuery.fn.autoResize 1.1 3 * -- 4 * https://github.com/alexbardas/jQuery.fn.autoResize 5 * -- 6 * This program is free software. It comes without any warranty, to 7 * the extent permitted by applicable law. You can redistribute it 8 * and/or modify it under the terms of the Do What The Fuck You Want 9 * To Public License, Version 2, as published by Sam Hocevar. See 10 * http://sam.zoy.org/wtfpl/COPYING for more details. */ 11 12(function($){ 13 14 var defaults = autoResize.defaults = { 15 onResize: function(){}, 16 animate: { 17 duration: 200, 18 complete: function(){} 19 }, 20 extraSpace: 50, 21 minHeight: 'original', 22 maxHeight: 500, 23 minWidth: 'original', 24 maxWidth: 500 25 }; 26 27 autoResize.cloneCSSProperties = [ 28 'lineHeight', 'textDecoration', 'letterSpacing', 29 'fontSize', 'fontFamily', 'fontStyle', 'fontWeight', 30 'textTransform', 'textAlign', 'direction', 'wordSpacing', 'fontSizeAdjust', 31 'padding' 32 ]; 33 34 autoResize.cloneCSSValues = { 35 position: 'absolute', 36 top: -9999, 37 left: -9999, 38 opacity: 0, 39 overflow: 'hidden' 40 }; 41 42 autoResize.resizableFilterSelector = 'textarea,input:not(input[type]),input[type=text],input[type=password]'; 43 44 autoResize.AutoResizer = AutoResizer; 45 46 $.fn.autoResize = autoResize; 47 48 function autoResize(config) { 49 this.filter(autoResize.resizableFilterSelector).each(function(){ 50 new AutoResizer( $(this), config ); 51 }); 52 return this; 53 } 54 55 function AutoResizer(el, config) { 56 57 config = this.config = $.extend(autoResize.defaults, config); 58 this.el = el; 59 60 this.nodeName = el[0].nodeName.toLowerCase(); 61 62 this.originalHeight = el.height(); 63 this.previousScrollTop = null; 64 65 this.value = el.val(); 66 67 if (config.maxWidth === 'original') config.maxWidth = el.width(); 68 if (config.minWidth === 'original') config.minWidth = el.width(); 69 if (config.maxHeight === 'original') config.maxHeight = el.height(); 70 if (config.minHeight === 'original') config.minHeight = el.height(); 71 72 if (this.nodeName === 'textarea') { 73 el.css({ 74 resize: 'none', 75 overflowY: 'hidden' 76 }); 77 } 78 79 el.data('AutoResizer', this); 80 81 this.createClone(); 82 this.injectClone(); 83 this.bind(); 84 85 } 86 87 AutoResizer.prototype = { 88 89 bind: function() { 90 91 var check = $.proxy(function(){ 92 this.check(); 93 return true; 94 }, this); 95 96 this.unbind(); 97 98 this.el 99 .bind('keyup.autoResize', check) 100 //.bind('keydown.autoResize', check) 101 .bind('change.autoResize', check); 102 103 this.check(null, true); 104 105 }, 106 107 unbind: function() { 108 this.el.unbind('.autoResize'); 109 }, 110 111 createClone: function() { 112 113 var el = this.el, 114 clone; 115 116 if (this.nodeName === 'textarea') { 117 clone = el.clone().height('auto'); 118 } else { 119 clone = $('<span/>').width('auto').css({ 120 whiteSpace: 'nowrap' 121 }); 122 } 123 124 this.clone = clone; 125 126 $.each(autoResize.cloneCSSProperties, function(i, p){ 127 clone[0].style[p] = el.css(p); 128 }); 129 130 clone 131 .removeAttr('name') 132 .removeAttr('id') 133 .attr('tabIndex', -1) 134 .css(autoResize.cloneCSSValues); 135 136 }, 137 138 check: function(e, immediate) { 139 140 var config = this.config, 141 clone = this.clone, 142 el = this.el, 143 value = el.val(); 144 145 if (this.nodeName === 'input') { 146 147 clone.text(value); 148 149 // Calculate new width + whether to change 150 var cloneWidth = clone.width(), 151 newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ? 152 cloneWidth + config.extraSpace : config.minWidth, 153 currentWidth = el.width(); 154 155 newWidth = Math.min(newWidth, config.maxWidth); 156 157 if ( 158 (newWidth < currentWidth && newWidth >= config.minWidth) || 159 (newWidth >= config.minWidth && newWidth <= config.maxWidth) 160 ) { 161 162 config.onResize.call(el); 163 164 el.scrollLeft(0); 165 166 config.animate && !immediate ? 167 el.stop(1,1).animate({ 168 width: newWidth 169 }, config.animate) 170 : el.width(newWidth); 171 172 } 173 174 return; 175 176 } 177 178 // TEXTAREA 179 180 clone.height(0).val(value).scrollTop(10000); 181 182 var scrollTop = clone[0].scrollTop + config.extraSpace; 183 184 // Don't do anything if scrollTop hasen't changed: 185 if (this.previousScrollTop === scrollTop) { 186 return; 187 } 188 189 this.previousScrollTop = scrollTop; 190 191 if (scrollTop >= config.maxHeight) { 192 el.height(config.maxHeight); //JS 2013-07-03 Fixed bug. Now resizing to maxHeight if too high. 193 el.css('overflowY', ''); 194 return; 195 } 196 197 el.css('overflowY', 'hidden'); 198 199 if (scrollTop < config.minHeight) { 200 scrollTop = config.minHeight; 201 } 202 203 config.onResize.call(el); 204 205 // Either animate or directly apply height: 206 config.animate && !immediate ?
207 el.stop(1,1).animate({ 208 height: scrollTop 209 }, config.animate) 210 : el.height(scrollTop); 211 212 }, 213 214 destroy: function() { 215 this.unbind(); 216 this.el.removeData('AutoResizer'); 217 this.clone.remove(); 218 delete this.el; 219 delete this.clone; 220 }, 221 222 injectClone: function() { 223 ( 224 autoResize.cloneContainer || 225 (autoResize.cloneContainer = $('<arclones/>').appendTo('body')) 226 ).append(this.clone); 227 } 228 229 }; 230 231})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.