You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.3 KiB
130 lines
4.3 KiB
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; |
|
} |
|
}); |
|
});
|
|
|