From cea135066ed10e281b47b8db7cf63709c0b4e3ad Mon Sep 17 00:00:00 2001 From: Jack Moore Date: Wed, 15 Apr 2015 14:45:20 -0400 Subject: [PATCH] v3.0.0 - renamed events and added new methods. --- bower.json | 2 +- dest/autosize.js | 163 +++++++++++++++++++++++++------------------ dest/autosize.min.js | 4 +- package.json | 5 +- readme.md | 119 ++----------------------------- 5 files changed, 107 insertions(+), 186 deletions(-) diff --git a/bower.json b/bower.json index fd20522..08968ee 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "autosize", "description": "Autosize is a small, stand-alone script to automatically adjust textarea height to fit text.", - "version": "2.0.1", + "version": "3.0.0", "dependencies": {}, "keywords": [ "textarea", diff --git a/dest/autosize.js b/dest/autosize.js index 48d17a7..4ac4b96 100644 --- a/dest/autosize.js +++ b/dest/autosize.js @@ -1,28 +1,27 @@ /*! - Autosize 2.0.1 + Autosize 3.0.0 license: MIT http://www.jacklmoore.com/autosize */ -(function (root, factory) { - 'use strict'; - +(function (global, factory) { if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], factory); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); + define(['exports', 'module'], factory); + } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') { + factory(exports, module); } else { - // Browser globals (root is window) - root.autosize = factory(); - } -}(this, function () { - function main(ta) { - if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || ta.hasAttribute('data-autosize-on')) { return; } - - var maxHeight; + var mod = { + exports: {} + }; + factory(mod.exports, mod); + global.autosize = mod.exports; + } +})(this, function (exports, module) { + 'use strict'; + + function assign(ta) { + if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || ta.hasAttribute('data-autosize-on')) { + return; + }var maxHeight; var heightOffset; function init() { @@ -34,11 +33,8 @@ ta.style.resize = 'horizontal'; } - // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width - ta.style.wordWrap = 'break-word'; - // Chrome/Safari-specific fix: - // When the textarea y-overflow is hidden, Chrome/Safari doesn't reflow the text to account for the space + // When the textarea y-over is hidden, Chrome/Safari doesn't reflow the text to account for the space // made available by removing the scrollbar. This workaround will cause the text to reflow. var width = ta.style.width; ta.style.width = '0px'; @@ -49,24 +45,24 @@ ta.style.width = width; maxHeight = style.maxHeight !== 'none' ? parseFloat(style.maxHeight) : false; - + if (style.boxSizing === 'content-box') { - heightOffset = -(parseFloat(style.paddingTop)+parseFloat(style.paddingBottom)); + heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)); } else { - heightOffset = parseFloat(style.borderTopWidth)+parseFloat(style.borderBottomWidth); + heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); } - adjust(); + update(); } - function adjust() { + function update() { var startHeight = ta.style.height; var htmlTop = document.documentElement.scrollTop; var bodyTop = document.body.scrollTop; - + ta.style.height = 'auto'; - var endHeight = ta.scrollHeight+heightOffset; + var endHeight = ta.scrollHeight + heightOffset; if (maxHeight !== false && maxHeight < endHeight) { endHeight = maxHeight; @@ -77,7 +73,7 @@ ta.style.overflowY = 'hidden'; } - ta.style.height = endHeight+'px'; + ta.style.height = endHeight + 'px'; // prevents scroll-position jumping document.documentElement.scrollTop = htmlTop; @@ -85,62 +81,97 @@ if (startHeight !== ta.style.height) { var evt = document.createEvent('Event'); - evt.initEvent('autosize.resized', true, false); + evt.initEvent('autosize:resized', true, false); ta.dispatchEvent(evt); } } - // IE9 does not fire onpropertychange or oninput for deletions, - // so binding to onkeyup to catch most of those events. - // There is no way that I know of to detect something like 'cut' in IE9. - if ('onpropertychange' in ta && 'oninput' in ta) { - ta.addEventListener('keyup', adjust); - } - - window.addEventListener('resize', adjust); - ta.addEventListener('input', adjust); - - ta.addEventListener('autosize.update', adjust); - - ta.addEventListener('autosize.destroy', function(style){ - window.removeEventListener('resize', adjust); - ta.removeEventListener('input', adjust); - ta.removeEventListener('keyup', adjust); - ta.removeEventListener('autosize.destroy'); + ta.addEventListener('autosize:destroy', (function (style) { + window.removeEventListener('resize', update); + ta.removeEventListener('input', update); + ta.removeEventListener('keyup', update); + ta.removeAttribute('data-autosize-on'); + ta.removeEventListener('autosize:destroy'); - Object.keys(style).forEach(function(key){ + Object.keys(style).forEach(function (key) { ta.style[key] = style[key]; }); - - ta.removeAttribute('data-autosize-on'); - }.bind(ta, { + }).bind(ta, { height: ta.style.height, - overflow: ta.style.overflow, overflowY: ta.style.overflowY, - wordWrap: ta.style.wordWrap, resize: ta.style.resize })); + // IE9 does not fire onpropertychange or oninput for deletions, + // so binding to onkeyup to catch most of those events. + // There is no way that I know of to detect something like 'cut' in IE9. + if ('onpropertychange' in ta && 'oninput' in ta) { + ta.addEventListener('keyup', update); + } + + window.addEventListener('resize', update); + ta.addEventListener('input', update); + ta.addEventListener('autosize:update', update); ta.setAttribute('data-autosize-on', true); - ta.style.overflow = 'hidden'; ta.style.overflowY = 'hidden'; + init(); + } + + function destroy(ta) { + if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA') { + return; + }var evt = document.createEvent('Event'); + evt.initEvent('autosize:destroy', true, false); + ta.dispatchEvent(evt); + } - init(); + function update(ta) { + if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) { + return; + }var evt = document.createEvent('Event'); + evt.initEvent('autosize:update', true, false); + ta.dispatchEvent(evt); } + var autosize; + // Do nothing in IE8 or lower if (typeof window.getComputedStyle !== 'function') { - return function(elements) { - return elements; + autosize = function (el) { + return el; + }; + autosize.destroy = function (el) { + return el; + }; + autosize.update = function (el) { + return el; }; } else { - return function(elements) { - if (elements && elements.length) { - Array.prototype.forEach.call(elements, main); - } else if (elements && elements.nodeName) { - main(elements); + autosize = function (el) { + if (el && el.length) { + Array.prototype.forEach.call(el, assign); + } else if (el && el.nodeName) { + assign(el); } - return elements; + return el; + }; + autosize.destroy = function (el) { + if (el && el.length) { + Array.prototype.forEach.call(el, destroy); + } else if (el && el.nodeName) { + destroy(el); + } + return el; + }; + autosize.update = function (el) { + if (el && el.length) { + Array.prototype.forEach.call(el, update); + } else if (el && el.nodeName) { + update(el); + } + return el; }; } -})); + + module.exports = autosize; +}); \ No newline at end of file diff --git a/dest/autosize.min.js b/dest/autosize.min.js index ec0a0a9..f4979df 100644 --- a/dest/autosize.min.js +++ b/dest/autosize.min.js @@ -1,6 +1,6 @@ /*! - Autosize 2.0.1 + Autosize 3.0.0 license: MIT http://www.jacklmoore.com/autosize */ -!function(e,t){"use strict";"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.autosize=t()}(this,function(){function e(e){function t(){var t=window.getComputedStyle(e,null);"vertical"===t.resize?e.style.resize="none":"both"===t.resize&&(e.style.resize="horizontal"),e.style.wordWrap="break-word";var i=e.style.width;e.style.width="0px",e.offsetWidth,e.style.width=i,n="none"!==t.maxHeight?parseFloat(t.maxHeight):!1,r="content-box"===t.boxSizing?-(parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)):parseFloat(t.borderTopWidth)+parseFloat(t.borderBottomWidth),o()}function o(){var t=e.style.height,o=document.documentElement.scrollTop,i=document.body.scrollTop;e.style.height="auto";var s=e.scrollHeight+r;if(n!==!1&&s>n?(s=n,"scroll"!==e.style.overflowY&&(e.style.overflowY="scroll")):"hidden"!==e.style.overflowY&&(e.style.overflowY="hidden"),e.style.height=s+"px",document.documentElement.scrollTop=o,document.body.scrollTop=i,t!==e.style.height){var d=document.createEvent("Event");d.initEvent("autosize.resized",!0,!1),e.dispatchEvent(d)}}if(e&&e.nodeName&&"TEXTAREA"===e.nodeName&&!e.hasAttribute("data-autosize-on")){var n,r;"onpropertychange"in e&&"oninput"in e&&e.addEventListener("keyup",o),window.addEventListener("resize",o),e.addEventListener("input",o),e.addEventListener("autosize.update",o),e.addEventListener("autosize.destroy",function(t){window.removeEventListener("resize",o),e.removeEventListener("input",o),e.removeEventListener("keyup",o),e.removeEventListener("autosize.destroy"),Object.keys(t).forEach(function(o){e.style[o]=t[o]}),e.removeAttribute("data-autosize-on")}.bind(e,{height:e.style.height,overflow:e.style.overflow,overflowY:e.style.overflowY,wordWrap:e.style.wordWrap,resize:e.style.resize})),e.setAttribute("data-autosize-on",!0),e.style.overflow="hidden",e.style.overflowY="hidden",t()}}return"function"!=typeof window.getComputedStyle?function(e){return e}:function(t){return t&&t.length?Array.prototype.forEach.call(t,e):t&&t.nodeName&&e(t),t}}); \ No newline at end of file +!function(e,t){if("function"==typeof define&&define.amd)define(["exports","module"],t);else if("undefined"!=typeof exports&&"undefined"!=typeof module)t(exports,module);else{var o={exports:{}};t(o.exports,o),e.autosize=o.exports}}(this,function(e,t){"use strict";function o(e){function t(){var t=window.getComputedStyle(e,null);"vertical"===t.resize?e.style.resize="none":"both"===t.resize&&(e.style.resize="horizontal");var r=e.style.width;e.style.width="0px",e.offsetWidth,e.style.width=r,n="none"!==t.maxHeight?parseFloat(t.maxHeight):!1,i="content-box"===t.boxSizing?-(parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)):parseFloat(t.borderTopWidth)+parseFloat(t.borderBottomWidth),o()}function o(){var t=e.style.height,o=document.documentElement.scrollTop,r=document.body.scrollTop;e.style.height="auto";var d=e.scrollHeight+i;if(n!==!1&&d>n?(d=n,"scroll"!==e.style.overflowY&&(e.style.overflowY="scroll")):"hidden"!==e.style.overflowY&&(e.style.overflowY="hidden"),e.style.height=d+"px",document.documentElement.scrollTop=o,document.body.scrollTop=r,t!==e.style.height){var s=document.createEvent("Event");s.initEvent("autosize:resized",!0,!1),e.dispatchEvent(s)}}if(e&&e.nodeName&&"TEXTAREA"===e.nodeName&&!e.hasAttribute("data-autosize-on")){var n,i;e.addEventListener("autosize:destroy",function(t){window.removeEventListener("resize",o),e.removeEventListener("input",o),e.removeEventListener("keyup",o),e.removeAttribute("data-autosize-on"),e.removeEventListener("autosize:destroy"),Object.keys(t).forEach(function(o){e.style[o]=t[o]})}.bind(e,{height:e.style.height,overflowY:e.style.overflowY,resize:e.style.resize})),"onpropertychange"in e&&"oninput"in e&&e.addEventListener("keyup",o),window.addEventListener("resize",o),e.addEventListener("input",o),e.addEventListener("autosize:update",o),e.setAttribute("data-autosize-on",!0),e.style.overflowY="hidden",t()}}function n(e){if(e&&e.nodeName&&"TEXTAREA"===e.nodeName){var t=document.createEvent("Event");t.initEvent("autosize:destroy",!0,!1),e.dispatchEvent(t)}}function i(e){if(e&&e.nodeName&&"TEXTAREA"===e.nodeName){var t=document.createEvent("Event");t.initEvent("autosize:update",!0,!1),e.dispatchEvent(t)}}var r;"function"!=typeof window.getComputedStyle?(r=function(e){return e},r.destroy=function(e){return e},r.update=function(e){return e}):(r=function(e){return e&&e.length?Array.prototype.forEach.call(e,o):e&&e.nodeName&&o(e),e},r.destroy=function(e){return e&&e.length?Array.prototype.forEach.call(e,n):e&&e.nodeName&&n(e),e},r.update=function(e){return e&&e.length?Array.prototype.forEach.call(e,i):e&&e.nodeName&&i(e),e}),t.exports=r}); \ No newline at end of file diff --git a/package.json b/package.json index 40cb2c0..bdc3f32 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "autosize", "description": "Autosize is a small, stand-alone script to automatically adjust textarea height to fit text.", - "version": "2.0.1", + "version": "3.0.0", "keywords": [ "textarea", "form", @@ -24,8 +24,7 @@ "devDependencies": { "babel": "^5.1.9", "jshint": "^2.5.6", - "uglify-js": "^2.4.15", - "watch": "^0.14.0" + "uglify-js": "^2.4.15" }, "config": { "bower": { diff --git a/readme.md b/readme.md index 3c5c2ee..386fe11 100644 --- a/readme.md +++ b/readme.md @@ -2,15 +2,11 @@ Autosize is a small, stand-alone script to automatically adjust textarea height to fit text. -## Install - -[Download zip](https://github.com/jackmoore/autosize/archive/master.zip) - -##### Install via NPM +#### Install via NPM ```bash npm install autosize ``` -##### Install via Bower +#### Install via Bower ```bash bower install autosize ``` @@ -21,7 +17,7 @@ Chrome | Firefox | IE | Safari | iOS Safari | Android | Opera Mini ------ | --------|----|--------|------------|---------|------------ yes | yes | 9 | yes | yes | 4 | ? -### Usage +#### Usage The autosize function accepts a single textarea element, or an array or array-like object (such as a NodeList or jQuery collection) of textarea elements. @@ -36,111 +32,6 @@ autosize(document.querySelector('textarea')); autosize($('textarea')); ``` -### Lifecycle Events - -##### autosize.update (triggerable) - -Once you've assigned autosize to an element, you can manually trigger the resize event by using the 'autosize.update' event. Autosize has no way of knowing when a script has changed the value of a textarea element, or when the textarea element styles have changed, so this event would be used instruct autosize to resize the textarea. - - -```javascript -var ta = document.querySelector('textarea'); - -autosize(ta); - -// Change the value of the textarea -ta.value = "Something really long"; -ta.style.fontSize = '20px'; - -// Dispatch a 'autosize.update' event to trigger a resize: -var evt = document.createEvent('Event'); -evt.initEvent('autosize.update', true, false); -ta.dispatchEvent(evt); -``` - -##### autosize.destroy (triggerable) - -```javascript -var ta = document.querySelector('textarea'); - -// assign autosize to ta -autosize(ta); - -// remove autosize from ta -var evt = document.createEvent('Event'); -evt.initEvent('autosize.destroy', true, false); -ta.dispatchEvent(evt); -``` - -##### autosize.resized (observable) - -This event is fired every time autosize adjusts the textarea height. - -```javascript -var ta = document.querySelector('textarea'); - -ta.addEventListener('autosize.resized', function(){ - console.log('textarea height updated'); -}); -``` - -### Differences between v2 and v1 - -If you need the v1 version for whatever reason, you can find it in the v1 branch on Github: -[https://github.com/jackmoore/autosize/tree/v1](https://github.com/jackmoore/autosize/tree/v1) - -Autosize v2 is a smaller, simplier script than v1. It is now a stand-alone script instead of a jQuery plugin, and support for IE8 and lower has been dropped (legacy IE users will be presented with an unmodified textarea element). Additionally, Autosize v2 does not take in any optional parameters at this time. - -Autosize v2 does not create a mirror textarea element in order to calculate the correct height, which was responsible for much of the original script's complexity. This should be more efficient and reliable, but the new method prevents using a CSS transition to animate the height change. - - -### Converting to a jQuery plugin - -Autosize does not depend on jQuery, but it can easily be turned into a jQuery plugin if desired. - -```javascript -// Create the plugin: -window.jQuery.fn.autosize = function() { - return autosize(this); -}; - -// Use the plugin: -jQuery(function($){ - $('textarea').autosize(); -}); -``` - -### Known Issues & Solutions - -#### Incorrect size with hidden textarea elements - -Autosize needs to be able to calculate the width of the textarea element when it is assigned. JavaScript cannot accurately calculate the width of an element that has been removed from the document flow. If you want to assign Autosize to a hidden textarea element, be sure to either specify the pixel width of the element in your CSS, or trigger the `autosize.update` event after you reveal the textarea element. - -**Possible ways to resolve:** - -* Specify an exact width for the textarea element in your stylesheet. -* Wait until after the textarea element has been revealed before assigning Autosize. -* Trigger the `autosize.update` event after the element has been revealed. - -```javascript -var ta = document.querySelector('textarea'); -ta.style.display = 'none'; -autosize(ta); -ta.style.display = ''; - -// Trigger the autosize.update event to recalculate the size: -var evt = document.createEvent('Event'); -evt.initEvent('autosize.update', true, false); -ta.dispatchEvent(evt); -``` - -* Wait until the textarea has been focused by the user before assigning Autosize. - -```javascript -var ta = document.querySelector('textarea'); -ta.addEventListener('focus', function(){ - autosize(ta); -}); -``` +Full documentation can be found at [jacklmoore.com/autosize](http://jacklmoore.com/autosize) -Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php) +Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php) \ No newline at end of file