1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
define("dijit/form/_ExpandingTextAreaMixin", [
"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;
}
});
});
|