_ExpandingTextAreaMixin.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dijit.form._ExpandingTextAreaMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dijit.form._ExpandingTextAreaMixin"] = true;
  8. dojo.provide("dijit.form._ExpandingTextAreaMixin");
  9. // module:
  10. // dijit/form/_ExpandingTextAreaMixin
  11. // summary:
  12. // Mixin for textarea widgets to add auto-expanding capability
  13. // feature detection
  14. var needsHelpShrinking;
  15. dojo.declare("dijit.form._ExpandingTextAreaMixin", null, {
  16. // summary:
  17. // Mixin for textarea widgets to add auto-expanding capability
  18. _setValueAttr: function(){
  19. this.inherited(arguments);
  20. this.resize();
  21. },
  22. postCreate: function(){
  23. this.inherited(arguments);
  24. var textarea = this.textbox;
  25. if(needsHelpShrinking == undefined){
  26. var te = dojo.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' }}, dojo.body(), "last");
  27. needsHelpShrinking = te.scrollHeight >= te.clientHeight;
  28. dojo.body().removeChild(te);
  29. }
  30. this.connect(textarea, "onresize", "_resizeLater");
  31. this.connect(textarea, "onfocus", "_resizeLater");
  32. textarea.style.overflowY = "hidden";
  33. },
  34. startup: function(){
  35. this.inherited(arguments);
  36. this._resizeLater();
  37. },
  38. _onInput: function(e){
  39. this.inherited(arguments);
  40. this.resize();
  41. },
  42. _estimateHeight: function(){
  43. // summary:
  44. // Approximate the height when the textarea is invisible with the number of lines in the text.
  45. // Fails when someone calls setValue with a long wrapping line, but the layout fixes itself when the user clicks inside so . . .
  46. // In IE, the resize event is supposed to fire when the textarea becomes visible again and that will correct the size automatically.
  47. //
  48. var textarea = this.textbox;
  49. // #rows = #newlines+1
  50. textarea.rows = (textarea.value.match(/\n/g) || []).length + 1;
  51. },
  52. _resizeLater: function(){
  53. this.defer("resize");
  54. },
  55. resize: function(){
  56. // summary:
  57. // Resizes the textarea vertically (should be called after a style/value change)
  58. var textarea = this.textbox;
  59. function textareaScrollHeight(){
  60. var empty = false;
  61. if(textarea.value === ''){
  62. textarea.value = ' ';
  63. empty = true;
  64. }
  65. var sh = textarea.scrollHeight;
  66. if(empty){ textarea.value = ''; }
  67. return sh;
  68. }
  69. if(textarea.style.overflowY == "hidden"){ textarea.scrollTop = 0; }
  70. if(this.busyResizing){ return; }
  71. this.busyResizing = true;
  72. if(textareaScrollHeight() || textarea.offsetHeight){
  73. var newH = textareaScrollHeight() + Math.max(textarea.offsetHeight - textarea.clientHeight, 0);
  74. var newHpx = newH + "px";
  75. if(newHpx != textarea.style.height){
  76. textarea.style.height = newHpx;
  77. textarea.rows = 1; // rows can act like a minHeight if not cleared
  78. }
  79. if(needsHelpShrinking){
  80. var origScrollHeight = textareaScrollHeight(),
  81. newScrollHeight = origScrollHeight,
  82. origMinHeight = textarea.style.minHeight,
  83. decrement = 4, // not too fast, not too slow
  84. thisScrollHeight,
  85. origScrollTop = textarea.scrollTop;
  86. textarea.style.minHeight = newHpx; // maintain current height
  87. textarea.style.height = "auto"; // allow scrollHeight to change
  88. while(newH > 0){
  89. textarea.style.minHeight = Math.max(newH - decrement, 4) + "px";
  90. thisScrollHeight = textareaScrollHeight();
  91. var change = newScrollHeight - thisScrollHeight;
  92. newH -= change;
  93. if(change < decrement){
  94. break; // scrollHeight didn't shrink
  95. }
  96. newScrollHeight = thisScrollHeight;
  97. decrement <<= 1;
  98. }
  99. textarea.style.height = newH + "px";
  100. textarea.style.minHeight = origMinHeight;
  101. textarea.scrollTop = origScrollTop;
  102. }
  103. textarea.style.overflowY = textareaScrollHeight() > textarea.clientHeight ? "auto" : "hidden";
  104. if(textarea.style.overflowY == "hidden"){ textarea.scrollTop = 0; }
  105. }else{
  106. // hidden content of unknown size
  107. this._estimateHeight();
  108. }
  109. this.busyResizing = false;
  110. }
  111. });
  112. }