UNPKG

dijit

Version:

Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u

131 lines (117 loc) 4.42 kB
define([ "dojo/_base/declare", // declare "dojo/dom-construct", // domConstruct.create "dojo/has", "dojo/_base/lang", // lang.hitch "dojo/on", "dojo/_base/window", // win.body "../Viewport" ], function(declare, domConstruct, has, lang, on, win, Viewport){ // module: // dijit/form/_ExpandingTextAreaMixin // feature detection, true for mozilla and webkit has.add("textarea-needs-help-shrinking", function(){ var body = win.body(), // note: if multiple documents exist, doesn't matter which one we use te = domConstruct.create('textarea', { rows:"5", cols:"20", value: ' ', style: {zoom:1, fontSize:"12px", height:"96px", overflow:'hidden', visibility:'hidden', position:'absolute', border:"5px solid white", margin:"0", padding:"0", boxSizing: 'border-box', MsBoxSizing: 'border-box', WebkitBoxSizing: 'border-box', MozBoxSizing: 'border-box' } }, body, "last"); var needsHelpShrinking = te.scrollHeight >= te.clientHeight; body.removeChild(te); return needsHelpShrinking; }); return declare("dijit.form._ExpandingTextAreaMixin", null, { // summary: // Mixin for textarea widgets to add auto-expanding capability _setValueAttr: function(){ this.inherited(arguments); this.resize(); }, postCreate: function(){ this.inherited(arguments); var textarea = this.textbox; textarea.style.overflowY = "hidden"; this.own(on(textarea, "focus, resize", lang.hitch(this, "_resizeLater"))); }, startup: function(){ this.inherited(arguments); this.own(Viewport.on("resize", lang.hitch(this, "_resizeLater"))); this._resizeLater(); }, _onInput: function(e){ this.inherited(arguments); this.resize(); }, _estimateHeight: function(){ // summary: // Approximate the height when the textarea is invisible with the number of lines in the text. // Fails when someone calls setValue with a long wrapping line, but the layout fixes itself when the user clicks inside so . . . // In IE, the resize event is supposed to fire when the textarea becomes visible again and that will correct the size automatically. // var textarea = this.textbox; // #rows = #newlines+1 textarea.rows = (textarea.value.match(/\n/g) || []).length + 1; }, _resizeLater: function(){ this.defer("resize"); }, resize: function(){ // summary: // Resizes the textarea vertically (should be called after a style/value change) var textarea = this.textbox; function textareaScrollHeight(){ var empty = false; if(textarea.value === ''){ textarea.value = ' '; empty = true; } var sh = textarea.scrollHeight; if(empty){ textarea.value = ''; } return sh; } if(textarea.style.overflowY == "hidden"){ textarea.scrollTop = 0; } if(this.busyResizing){ return; } this.busyResizing = true; if(textareaScrollHeight() || textarea.offsetHeight){ var newH = textareaScrollHeight() + Math.max(textarea.offsetHeight - textarea.clientHeight, 0); var newHpx = newH + "px"; if(newHpx != textarea.style.height){ textarea.style.height = newHpx; textarea.rows = 1; // rows can act like a minHeight if not cleared } if(has("textarea-needs-help-shrinking")){ var origScrollHeight = textareaScrollHeight(), newScrollHeight = origScrollHeight, origMinHeight = textarea.style.minHeight, decrement = 4, // not too fast, not too slow thisScrollHeight, origScrollTop = textarea.scrollTop; textarea.style.minHeight = newHpx; // maintain current height textarea.style.height = "auto"; // allow scrollHeight to change while(newH > 0){ textarea.style.minHeight = Math.max(newH - decrement, 4) + "px"; thisScrollHeight = textareaScrollHeight(); var change = newScrollHeight - thisScrollHeight; newH -= change; if(change < decrement){ break; // scrollHeight didn't shrink } newScrollHeight = thisScrollHeight; decrement <<= 1; } textarea.style.height = newH + "px"; textarea.style.minHeight = origMinHeight; textarea.scrollTop = origScrollTop; } textarea.style.overflowY = textareaScrollHeight() > textarea.clientHeight ? "auto" : "hidden"; if(textarea.style.overflowY == "hidden"){ textarea.scrollTop = 0; } }else{ // hidden content of unknown size this._estimateHeight(); } this.busyResizing = false; } }); });