123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 |
- // Copyright 2010 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview A content-aware textarea control that grows and shrinks
- * automatically. This implementation extends {@link goog.ui.Control}.
- * This code is inspired by Dojo Dijit's Textarea implementation with
- * modifications to support native (when available) textarea resizing and
- * minHeight and maxHeight enforcement.
- *
- * @see ../demos/textarea.html
- */
- goog.provide('goog.ui.Textarea');
- goog.provide('goog.ui.Textarea.EventType');
- goog.require('goog.asserts');
- goog.require('goog.dom');
- goog.require('goog.dom.classlist');
- goog.require('goog.events.EventType');
- goog.require('goog.style');
- goog.require('goog.ui.Control');
- goog.require('goog.ui.TextareaRenderer');
- goog.require('goog.userAgent');
- /**
- * A textarea control to handle growing/shrinking with textarea.value.
- *
- * @param {string} content Text to set as the textarea's value.
- * @param {goog.ui.TextareaRenderer=} opt_renderer Renderer used to render or
- * decorate the textarea. Defaults to {@link goog.ui.TextareaRenderer}.
- * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
- * document interaction.
- * @constructor
- * @extends {goog.ui.Control}
- */
- goog.ui.Textarea = function(content, opt_renderer, opt_domHelper) {
- goog.ui.Control.call(
- this, content, opt_renderer || goog.ui.TextareaRenderer.getInstance(),
- opt_domHelper);
- this.setHandleMouseEvents(false);
- this.setAllowTextSelection(true);
- this.hasUserInput_ = (content != '');
- if (!content) {
- this.setContentInternal('');
- }
- };
- goog.inherits(goog.ui.Textarea, goog.ui.Control);
- goog.tagUnsealableClass(goog.ui.Textarea);
- /**
- * Some UAs will shrink the textarea automatically, some won't.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.NEEDS_HELP_SHRINKING_ =
- !(goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(11));
- /**
- * True if the resizing function is executing, false otherwise.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.isResizing_ = false;
- /**
- * Represents if we have focus on the textarea element, used only
- * to render the placeholder if we don't have native placeholder
- * support.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.hasFocusForPlaceholder_ = false;
- /**
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.hasUserInput_ = false;
- /**
- * The height of the textarea as last measured.
- * @type {number}
- * @private
- */
- goog.ui.Textarea.prototype.height_ = 0;
- /**
- * A maximum height for the textarea. When set to 0, the default, there is no
- * enforcement of this value during resize.
- * @type {number}
- * @private
- */
- goog.ui.Textarea.prototype.maxHeight_ = 0;
- /**
- * A minimum height for the textarea. When set to 0, the default, there is no
- * enforcement of this value during resize.
- * @type {number}
- * @private
- */
- goog.ui.Textarea.prototype.minHeight_ = 0;
- /**
- * Whether or not textarea rendering characteristics have been discovered.
- * Specifically we determine, at runtime:
- * If the padding and border box is included in offsetHeight.
- * @see {goog.ui.Textarea.prototype.needsPaddingBorderFix_}
- * If the padding and border box is included in scrollHeight.
- * @see {goog.ui.Textarea.prototype.scrollHeightIncludesPadding_} and
- * @see {goog.ui.Textarea.prototype.scrollHeightIncludesBorder_}
- * TODO(user): See if we can determine goog.ui.Textarea.NEEDS_HELP_SHRINKING_.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.hasDiscoveredTextareaCharacteristics_ = false;
- /**
- * If a user agent doesn't correctly support the box-sizing:border-box CSS
- * value then we'll need to adjust our height calculations.
- * @see {goog.ui.Textarea.prototype.discoverTextareaCharacteristics_}
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.needsPaddingBorderFix_ = false;
- /**
- * Whether or not scrollHeight of a textarea includes the padding box.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.scrollHeightIncludesPadding_ = false;
- /**
- * Whether or not scrollHeight of a textarea includes the border box.
- * @type {boolean}
- * @private
- */
- goog.ui.Textarea.prototype.scrollHeightIncludesBorder_ = false;
- /**
- * For storing the padding box size during enterDocument, to prevent possible
- * measurement differences that can happen after text zooming.
- * Note: runtime padding changes will cause problems with this.
- * @type {goog.math.Box}
- * @private
- */
- goog.ui.Textarea.prototype.paddingBox_;
- /**
- * For storing the border box size during enterDocument, to prevent possible
- * measurement differences that can happen after text zooming.
- * Note: runtime border width changes will cause problems with this.
- * @type {goog.math.Box}
- * @private
- */
- goog.ui.Textarea.prototype.borderBox_;
- /**
- * Default text content for the textarea when it is unchanged and unfocussed.
- * We use the placeholder attribute for all browsers that have support for
- * it (new in HTML5 for the following browsers:
- *
- * Internet Explorer 10.0
- * Firefox 4.0
- * Opera 11.6
- * Chrome 4.0
- * Safari 5.0
- *
- * For older browsers, we save the placeholderText_ and set it as the element's
- * value and add the TEXTAREA_PLACEHOLDER_CLASS to indicate that it's a
- * placeholder string.
- * @type {string}
- * @private
- */
- goog.ui.Textarea.prototype.placeholderText_ = '';
- /**
- * Constants for event names.
- * @enum {string}
- */
- goog.ui.Textarea.EventType = {
- RESIZE: 'resize'
- };
- /**
- * Sets the default text for the textarea.
- * @param {string} text The default text for the textarea.
- */
- goog.ui.Textarea.prototype.setPlaceholder = function(text) {
- this.placeholderText_ = text;
- if (this.getElement()) {
- this.restorePlaceholder_();
- }
- };
- /**
- * @return {number} The padding plus the border box height.
- * @private
- */
- goog.ui.Textarea.prototype.getPaddingBorderBoxHeight_ = function() {
- var paddingBorderBoxHeight = this.paddingBox_.top + this.paddingBox_.bottom +
- this.borderBox_.top + this.borderBox_.bottom;
- return paddingBorderBoxHeight;
- };
- /**
- * @return {number} The minHeight value.
- */
- goog.ui.Textarea.prototype.getMinHeight = function() {
- return this.minHeight_;
- };
- /**
- * @return {number} The minHeight value with a potential padding fix.
- * @private
- */
- goog.ui.Textarea.prototype.getMinHeight_ = function() {
- var minHeight = this.minHeight_;
- var textarea = this.getElement();
- if (minHeight && textarea && this.needsPaddingBorderFix_) {
- minHeight -= this.getPaddingBorderBoxHeight_();
- }
- return minHeight;
- };
- /**
- * Sets a minimum height for the textarea, and calls resize if rendered.
- * @param {number} height New minHeight value.
- */
- goog.ui.Textarea.prototype.setMinHeight = function(height) {
- this.minHeight_ = height;
- this.resize();
- };
- /**
- * @return {number} The maxHeight value.
- */
- goog.ui.Textarea.prototype.getMaxHeight = function() {
- return this.maxHeight_;
- };
- /**
- * @return {number} The maxHeight value with a potential padding fix.
- * @private
- */
- goog.ui.Textarea.prototype.getMaxHeight_ = function() {
- var maxHeight = this.maxHeight_;
- var textarea = this.getElement();
- if (maxHeight && textarea && this.needsPaddingBorderFix_) {
- maxHeight -= this.getPaddingBorderBoxHeight_();
- }
- return maxHeight;
- };
- /**
- * Sets a maximum height for the textarea, and calls resize if rendered.
- * @param {number} height New maxHeight value.
- */
- goog.ui.Textarea.prototype.setMaxHeight = function(height) {
- this.maxHeight_ = height;
- this.resize();
- };
- /**
- * Sets the textarea's value.
- * @param {*} value The value property for the textarea, will be cast to a
- * string by the browser when setting textarea.value.
- */
- goog.ui.Textarea.prototype.setValue = function(value) {
- this.setContent(String(value));
- };
- /**
- * Gets the textarea's value.
- * @return {string} value The value of the textarea.
- */
- goog.ui.Textarea.prototype.getValue = function() {
- // We potentially have the placeholder stored in the value.
- // If a client of this class sets this.getElement().value directly
- // we don't set the this.hasUserInput_ boolean. Thus, we need to
- // explicitly check if the value != the placeholder text. This has
- // the unfortunate edge case of:
- // If the client sets this.getElement().value to the placeholder
- // text, we'll return the empty string.
- // The normal use case shouldn't be an issue, however, since the
- // default placeholderText is the empty string. Also, if the end user
- // inputs text, then this.hasUserInput_ will always be true.
- if (this.getElement().value != this.placeholderText_ ||
- this.supportsNativePlaceholder_() || this.hasUserInput_) {
- // We don't do anything fancy here.
- return this.getElement().value;
- }
- return '';
- };
- /** @override */
- goog.ui.Textarea.prototype.setContent = function(content) {
- goog.ui.Textarea.superClass_.setContent.call(this, content);
- this.hasUserInput_ = (content != '');
- this.resize();
- };
- /** @override **/
- goog.ui.Textarea.prototype.setEnabled = function(enable) {
- goog.ui.Textarea.superClass_.setEnabled.call(this, enable);
- this.getElement().disabled = !enable;
- };
- /**
- * Resizes the textarea vertically.
- */
- goog.ui.Textarea.prototype.resize = function() {
- if (this.getElement()) {
- this.grow_();
- }
- };
- /**
- * @return {boolean} True if the element supports the placeholder attribute.
- * @private
- */
- goog.ui.Textarea.prototype.supportsNativePlaceholder_ = function() {
- goog.asserts.assert(this.getElement());
- return 'placeholder' in this.getElement();
- };
- /**
- * Sets the value of the textarea element to the default text.
- * @private
- */
- goog.ui.Textarea.prototype.restorePlaceholder_ = function() {
- if (!this.placeholderText_) {
- // Return early if there is no placeholder to mess with.
- return;
- }
- // Check again in case something changed since this was scheduled.
- // We check that the element is still there since this is called by a timer
- // and the dispose method may have been called prior to this.
- if (this.supportsNativePlaceholder_()) {
- this.getElement().placeholder = this.placeholderText_;
- } else if (
- this.getElement() && !this.hasUserInput_ &&
- !this.hasFocusForPlaceholder_) {
- // We only want to set the value + placeholder CSS if we actually have
- // some placeholder text to show.
- goog.dom.classlist.add(
- goog.asserts.assert(this.getElement()),
- goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS);
- this.getElement().value = this.placeholderText_;
- }
- };
- /** @override **/
- goog.ui.Textarea.prototype.enterDocument = function() {
- goog.ui.Textarea.base(this, 'enterDocument');
- var textarea = this.getElement();
- // Eliminates the vertical scrollbar and changes the box-sizing mode for the
- // textarea to the border-box (aka quirksmode) paradigm.
- goog.style.setStyle(textarea, {
- 'overflowY': 'hidden',
- 'overflowX': 'auto',
- 'boxSizing': 'border-box',
- 'MsBoxSizing': 'border-box',
- 'WebkitBoxSizing': 'border-box',
- 'MozBoxSizing': 'border-box'
- });
- this.paddingBox_ = goog.style.getPaddingBox(textarea);
- this.borderBox_ = goog.style.getBorderBox(textarea);
- this.getHandler()
- .listen(textarea, goog.events.EventType.SCROLL, this.grow_)
- .listen(textarea, goog.events.EventType.FOCUS, this.grow_)
- .listen(textarea, goog.events.EventType.KEYUP, this.grow_)
- .listen(textarea, goog.events.EventType.MOUSEUP, this.mouseUpListener_)
- .listen(textarea, goog.events.EventType.BLUR, this.blur_);
- this.restorePlaceholder_();
- this.resize();
- };
- /**
- * Gets the textarea's content height + padding height + border height.
- * This is done by getting the scrollHeight and adjusting from there.
- * In the end this result is what we want the new offsetHeight to equal.
- * @return {number} The height of the textarea.
- * @private
- */
- goog.ui.Textarea.prototype.getHeight_ = function() {
- this.discoverTextareaCharacteristics_();
- var textarea = this.getElement();
- // Because enterDocument can be called even when the component is rendered
- // without being in a document, we may not have cached the correct paddingBox
- // data on render(). We try to make up for this here.
- if (isNaN(this.paddingBox_.top)) {
- this.paddingBox_ = goog.style.getPaddingBox(textarea);
- this.borderBox_ = goog.style.getBorderBox(textarea);
- }
- // Accounts for a possible (though unlikely) horizontal scrollbar.
- var height =
- this.getElement().scrollHeight + this.getHorizontalScrollBarHeight_();
- if (this.needsPaddingBorderFix_) {
- height -= this.getPaddingBorderBoxHeight_();
- } else {
- if (!this.scrollHeightIncludesPadding_) {
- var paddingBox = this.paddingBox_;
- var paddingBoxHeight = paddingBox.top + paddingBox.bottom;
- height += paddingBoxHeight;
- }
- if (!this.scrollHeightIncludesBorder_) {
- var borderBox = goog.style.getBorderBox(textarea);
- var borderBoxHeight = borderBox.top + borderBox.bottom;
- height += borderBoxHeight;
- }
- }
- return height;
- };
- /**
- * Sets the textarea's height.
- * @param {number} height The height to set.
- * @private
- */
- goog.ui.Textarea.prototype.setHeight_ = function(height) {
- if (this.height_ != height) {
- this.height_ = height;
- this.getElement().style.height = height + 'px';
- }
- };
- /**
- * Sets the textarea's rows attribute to be the number of newlines + 1.
- * This is necessary when the textarea is hidden, in which case scrollHeight
- * is not available.
- * @private
- */
- goog.ui.Textarea.prototype.setHeightToEstimate_ = function() {
- var textarea = this.getElement();
- textarea.style.height = 'auto';
- var newlines = textarea.value.match(/\n/g) || [];
- textarea.rows = newlines.length + 1;
- this.height_ = 0;
- };
- /**
- * Gets the the height of (possibly present) horizontal scrollbar.
- * @return {number} The height of the horizontal scrollbar.
- * @private
- */
- goog.ui.Textarea.prototype.getHorizontalScrollBarHeight_ = function() {
- var textarea = /** @type {!HTMLElement} */ (this.getElement());
- var height = textarea.offsetHeight - textarea.clientHeight;
- if (!this.scrollHeightIncludesPadding_) {
- var paddingBox = this.paddingBox_;
- var paddingBoxHeight = paddingBox.top + paddingBox.bottom;
- height -= paddingBoxHeight;
- }
- if (!this.scrollHeightIncludesBorder_) {
- var borderBox = goog.style.getBorderBox(textarea);
- var borderBoxHeight = borderBox.top + borderBox.bottom;
- height -= borderBoxHeight;
- }
- // Prevent negative number results, which sometimes show up.
- return height > 0 ? height : 0;
- };
- /**
- * In order to assess the correct height for a textarea, we need to know
- * whether the scrollHeight (the full height of the text) property includes
- * the values for padding and borders. We can also test whether the
- * box-sizing: border-box setting is working and then tweak accordingly.
- * Instead of hardcoding a list of currently known behaviors and testing
- * for quirksmode, we do a runtime check out of the flow. The performance
- * impact should be very small.
- * @private
- */
- goog.ui.Textarea.prototype.discoverTextareaCharacteristics_ = function() {
- if (!this.hasDiscoveredTextareaCharacteristics_) {
- var textarea =
- /** @type {!HTMLElement} */ (this.getElement().cloneNode(false));
- // We need to overwrite/write box model specific styles that might
- // affect height.
- goog.style.setStyle(textarea, {
- 'position': 'absolute',
- 'height': 'auto',
- 'top': '-9999px',
- 'margin': '0',
- 'padding': '1px',
- 'border': '1px solid #000',
- 'overflow': 'hidden'
- });
- goog.dom.appendChild(this.getDomHelper().getDocument().body, textarea);
- var initialScrollHeight = textarea.scrollHeight;
- textarea.style.padding = '10px';
- var paddingScrollHeight = textarea.scrollHeight;
- this.scrollHeightIncludesPadding_ =
- paddingScrollHeight > initialScrollHeight;
- initialScrollHeight = paddingScrollHeight;
- textarea.style.borderWidth = '10px';
- var borderScrollHeight = textarea.scrollHeight;
- this.scrollHeightIncludesBorder_ = borderScrollHeight > initialScrollHeight;
- // Tests if border-box sizing is working or not.
- textarea.style.height = '100px';
- var offsetHeightAtHeight100 = textarea.offsetHeight;
- if (offsetHeightAtHeight100 != 100) {
- this.needsPaddingBorderFix_ = true;
- }
- goog.dom.removeNode(textarea);
- this.hasDiscoveredTextareaCharacteristics_ = true;
- }
- };
- /**
- * The CSS class name to add to the input when the user has not entered a
- * value.
- */
- goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS =
- goog.getCssName('textarea-placeholder-input');
- /**
- * Called when the element goes out of focus.
- * @param {goog.events.Event=} opt_e The browser event.
- * @private
- */
- goog.ui.Textarea.prototype.blur_ = function(opt_e) {
- if (!this.supportsNativePlaceholder_()) {
- this.hasFocusForPlaceholder_ = false;
- if (this.getElement().value == '') {
- // Only transition to the default text if we have
- // no user input.
- this.hasUserInput_ = false;
- this.restorePlaceholder_();
- }
- }
- };
- /**
- * Resizes the textarea to grow/shrink to match its contents.
- * @param {goog.events.Event=} opt_e The browser event.
- * @private
- */
- goog.ui.Textarea.prototype.grow_ = function(opt_e) {
- if (this.isResizing_) {
- return;
- }
- var textarea = /** @type {!HTMLElement} */ (this.getElement());
- // If the element is getting focus and we don't support placeholders
- // natively, then remove the placeholder class.
- if (!this.supportsNativePlaceholder_() && opt_e &&
- opt_e.type == goog.events.EventType.FOCUS) {
- // We must have a textarea element, since we're growing it.
- // Remove the placeholder CSS + set the value to empty if we're currently
- // showing the placeholderText_ value if this is the first time we're
- // getting focus.
- if (textarea.value == this.placeholderText_ && this.placeholderText_ &&
- !this.hasFocusForPlaceholder_) {
- goog.dom.classlist.remove(
- textarea, goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS);
- textarea.value = '';
- }
- this.hasFocusForPlaceholder_ = true;
- this.hasUserInput_ = (textarea.value != '');
- }
- var shouldCallShrink = false;
- this.isResizing_ = true;
- var oldHeight = this.height_;
- if (textarea.scrollHeight) {
- var setMinHeight = false;
- var setMaxHeight = false;
- var newHeight = this.getHeight_();
- var currentHeight = textarea.offsetHeight;
- var minHeight = this.getMinHeight_();
- var maxHeight = this.getMaxHeight_();
- if (minHeight && newHeight < minHeight) {
- this.setHeight_(minHeight);
- setMinHeight = true;
- } else if (maxHeight && newHeight > maxHeight) {
- this.setHeight_(maxHeight);
- // If the content is greater than the height, we'll want the vertical
- // scrollbar back.
- textarea.style.overflowY = '';
- setMaxHeight = true;
- } else if (currentHeight != newHeight) {
- this.setHeight_(newHeight);
- // Makes sure that height_ is at least set.
- } else if (!this.height_) {
- this.height_ = newHeight;
- }
- if (!setMinHeight && !setMaxHeight &&
- goog.ui.Textarea.NEEDS_HELP_SHRINKING_) {
- shouldCallShrink = true;
- }
- } else {
- this.setHeightToEstimate_();
- }
- this.isResizing_ = false;
- if (shouldCallShrink) {
- this.shrink_();
- }
- if (oldHeight != this.height_) {
- this.dispatchEvent(goog.ui.Textarea.EventType.RESIZE);
- }
- };
- /**
- * Resizes the textarea to shrink to fit its contents. The way this works is
- * by increasing the padding of the textarea by 1px (it's important here that
- * we're in box-sizing: border-box mode). If the size of the textarea grows,
- * then the box is filled up to the padding box with text.
- * If it doesn't change, then we can shrink.
- * @private
- */
- goog.ui.Textarea.prototype.shrink_ = function() {
- var textarea = this.getElement();
- if (!this.isResizing_) {
- this.isResizing_ = true;
- var scrollHeight = textarea.scrollHeight;
- if (!scrollHeight) {
- this.setHeightToEstimate_();
- } else {
- var currentHeight = this.getHeight_();
- var minHeight = this.getMinHeight_();
- if (!(minHeight && currentHeight <= minHeight)) {
- // Nudge the padding by 1px.
- var paddingBox = this.paddingBox_;
- textarea.style.paddingBottom = paddingBox.bottom + 1 + 'px';
- var heightAfterNudge = this.getHeight_();
- // If the one px of padding had no effect, then we can shrink.
- if (heightAfterNudge == currentHeight) {
- textarea.style.paddingBottom =
- paddingBox.bottom + scrollHeight + 'px';
- textarea.scrollTop = 0;
- var shrinkToHeight = this.getHeight_() - scrollHeight;
- if (shrinkToHeight >= minHeight) {
- this.setHeight_(shrinkToHeight);
- } else {
- this.setHeight_(minHeight);
- }
- }
- textarea.style.paddingBottom = paddingBox.bottom + 'px';
- }
- }
- this.isResizing_ = false;
- }
- };
- /**
- * We use this listener to check if the textarea has been natively resized
- * and if so we reset minHeight so that we don't ever shrink smaller than
- * the user's manually set height. Note that we cannot check size on mousedown
- * and then just compare here because we cannot capture mousedown on
- * the textarea resizer, while mouseup fires reliably.
- * @param {goog.events.BrowserEvent} e The mousedown event.
- * @private
- */
- goog.ui.Textarea.prototype.mouseUpListener_ = function(e) {
- var textarea = /** @type {!HTMLElement} */ (this.getElement());
- var height = textarea.offsetHeight;
- // This solves for when the MSIE DropShadow filter is enabled,
- // as it affects the offsetHeight value, even with MsBoxSizing:border-box.
- if (textarea['filters'] && textarea['filters'].length) {
- var dropShadow =
- textarea['filters']['item']('DXImageTransform.Microsoft.DropShadow');
- if (dropShadow) {
- height -= dropShadow['offX'];
- }
- }
- if (height != this.height_) {
- this.minHeight_ = height;
- this.height_ = height;
- }
- };
|