xmmcn

textarea 多行文本域,大家所熟悉的,当对其设置了高度以后,如果里面的文本多了,那么就会出现滚动条.有些设计师觉得出现滚动条就是不友好的体现,那么我们就试着来消除它吧.

首先我对textarea设置height为确定的某值,然后设置overflow属性,其值为hidden,这样就能够去掉滚动条了,不论textarea里面的文本是多是少。现在问题又来了,如果这样设置的话,岂不是当文本很多的时候,很不友好吗?答案是对的,非常不友好,至少在我看来是这样的。

随后,我们进一步设想,如果textarea如果能够随着内容文本的增加为自适应的增加自身的height,这是不是很好呢?有想法了,就去做吧!

刚开始的时候,我的想法是,生成一个与当前textarea对应的div元素,设为隐藏,并且各种外观样式与textarea元素一致,然后我们对textarea绑定相关事件,同步二者之间的内容文本,这样,我们就可以取得div的高度了,然后我们设置textarea为这个高度。附上相关代码:

View Code
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>JQuery plugin textareaHeightAuto</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
*{margin: 0;padding: 0}
.textarea {overflow: hidden;margin: 50px;height: 100px;width: 400px;border: 1px solid #ccc;}
.button {padding: 5px 10px;cursor: pointer;}
</style>
</head>
<body>

<textarea id="J_Txt" class="textarea"></textarea>
<button type="button" id="J_Btn" class="button">destroy</button>

<script type="text/javascript">
;(function($){
    var methods = {
        init: function(options){
            debug(\'textareaHeightAuto start !\');
            var main_opts = $.extend({}, $.fn.textareaHeightAuto.defaults, options);
            return this.each(function(){
                var $this = $(this);
                var opts = main_opts;
                $this.data(\'textareaHeightAuto\', opts);
                var styles = {
                    width: $this.width(),
                    height: $this.height(),
                    padding: {
                        top: $this.css(\'padding-top\'),
                        right: $this.css(\'padding-right\'),
                        bottom: $this.css(\'padding-bottom\'),
                        left: $this.css(\'padding-left\')
                    },
                    margin: {
                        top: $this.css(\'margin-top\'),
                        right: $this.css(\'margin-right\'),
                        bottom: $this.css(\'margin-bottom\'),
                        left: $this.css(\'margin-left\')
                    },
                    border: {
                        width: $this.css(\'border-width\'),
                        style: $this.css(\'border-style\'),
                        color: $this.css(\'border-color\')
                    },
                    fontSize: $this.css(\'font-size\'),
                    fontFamily: $this.css(\'font-family\'),
                    lineHeight: $this.css(\'line-height\')
                };
                $this.css({overflow: \'hidden\', resize: \'none\'});
                var $textareaCloneDom = $(\'<div class="textareaCloneDom"></div>\');
                $textareaCloneDom.css({
                    \'display\': \'none\',
                    /*
                    \'margin-top\': styles.margin.top,
                    \'margin-right\': styles.margin.right,
                    \'margin-bottom\': styles.margin.bottom,
                    \'margin-left\': styles.margin.left,
                    */
                    \'padding-top\': styles.padding.top,
                    \'padding-right\': styles.padding.right,
                    \'padding-bottom\': styles.padding.bottom,
                    \'padding-left\': styles.padding.left,
                    \'width\': styles.width,
                    \'height\': \'auto\',
                    \'min-height\': styles.height,
                    \'font-size\': styles.fontSize,
                    \'font-family\': styles.fontFamily,
                    \'line-height\': styles.lineHeight,
                    \'word-wrap\': \'break-word\',
                    \'word-break\': \'normal\',
                    \'border\': styles.border.width +\' \'+ styles.border.style +\' \'+ styles.border.color
                });
                if($.browser.msie && $.browser.version == 6.0){
                    $textareaCloneDom.css({\'height\': styles.height});
                }
                $this.after($textareaCloneDom);
                var _val;

                $this.on(opts.eventName, function(e){
                    var $target = $(this);
                    _val = $target.val();
                    _val = _val.replace(/\n/g, \'<br />\');
                    $textareaCloneDom.html(_val+\'<br /><br />\');
                    $target.height($textareaCloneDom.height());
                });
            });
        },
        destroy: function(){
            return this.each(function(){
                var $this = $(this),
                    data = $this.data(\'textareaHeightAuto\');
                $this.siblings(\'div.textareaCloneDom\').remove();
                $this.off(data.eventName);
                $this.css({height: data.minHeight});
                $this.removeData(\'textareaHeightAuto\');
            });
        }
    };

    $.fn.textareaHeightAuto = function(method){
        if(methods[method]){
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }else if(typeof method === \'object\' || !method){
            return methods.init.apply(this, arguments);
        }else{
            $.error(\'Method \'+ method + \' does not exist on jQuery.textareaHeightAuto\');
        }
    };

    // 内部方法
    function debug(obj){
        if(window.console && window.console.log){
            window.console.log(obj);
        }
    }

    // 可以适当暴露一些可扩展的方法
    //$.fn.textareaHeightAuto.fun = function(str){};

    // 把默认参数放在外面,使得用户可以在插件之外就修改插件默认设置
    // $.fn.textareaHeightAuto.defaults.bottomHeight = 0;// 修改插件的默认设置
    // $(\'#textarea\').textareaHeightAuto({bottomHeight: 0});// 修改应用插件的当前元素的默认设置
    $.fn.textareaHeightAuto.defaults = {
        maxHeight: 600,
        minHeight: 100,
        bottomHeight: 18,
        eventName: \'paste cut keydown keyup focus blur\'
    };
})(jQuery);

$(document).ready(function(){
    $(\'#J_Txt\').textareaHeightAuto();

    $(\'#J_Btn\').on(\'click\', function(){
        $(\'#J_Txt\').textareaHeightAuto(\'destroy\');
        $(this).attr(\'disabled\', true);
    });
});
</script>
</body>
</html>

上面的做法虽然实现了相关的效果,但是感觉有些复杂了,我们是否还能对此改进呢?答案是肯定的!

后面我翻阅了相关资料,也搜索了类似的相关js,找到这么一个 scrollHeight 属性,手册上是这么解释该属性的:

scrollHeight是返回整个网页或某个元素内容的高度,然后再加上滚动条可以滚动的高度值.就是scrollHeight返回的正确结果

利用这个属性,我们可以大大的简化代码。附上代码:

View Code
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>JQuery plugin textareaHeightAuto</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
*{margin: 0;padding: 0}
.textarea {overflow: hidden;margin: 50px;height: 100px;width: 400px;border: 1px solid #ccc;}
.button {padding: 5px 10px;cursor: pointer;}
</style>
</head>
<body>

<textarea id="J_Txt" class="textarea"></textarea>
<button type="button" id="J_Btn" class="button">destroy</button>

<script type="text/javascript">
;(function($){
    var methods = {
        init: function(options){
            debug(\'textareaHeightAuto start !\');
            var main_opts = $.extend({}, $.fn.textareaHeightAuto.defaults, options);
            return this.each(function(){
                var $this = $(this);
                debug($this);
                //var opts = $.metadata ? $.extend({}, main_opts, $this.metadata()) : main_opts;
                var opts = main_opts;
                $this.data(\'textareaHeightAuto\', opts);
                $this.on(opts.eventName, function(){
                    var $target = $(this);
                    // 这里是比较重要的地方 必须先对textarea的高度进行设置,然后才能取 scrollHeight 的值
                    // 这是因为 scrollHeight 返回的是 元素内容的高度 + 滚动条可以滚动的高度值,明白了这点,下面就可以理解了
                    $target.height(opts.minHeight - opts.bottomHeight);// 增加这个间隔值是为了修复设置textarea高度时(特别是在最后一行回车时)跳动太大的情况
                    var scrollHeight = $target[0].scrollHeight + opts.bottomHeight;// 一加一减,相互抵消
                    if((scrollHeight) > opts.minHeight){
                        if(scrollHeight < opts.maxHeight){
                            $target.css({\'overflow-y\': \'hidden\'}).height(scrollHeight);
                        }else{
                            $target.css({\'overflow-y\': \'auto\'}).height(opts.maxHeight);
                        }
                    }else{
                        $target.css({\'overflow-y\': \'hidden\'}).height(opts.minHeight);
                    }
                });
            });
        },
        destroy: function(){
            return this.each(function(){
                var $this = $(this),
                    data = $this.data(\'textareaHeightAuto\');
                $this.off(data.eventName);
                $this.css({height: data.minHeight});// 不知道重置(还原?)textarea高度是否有必要
                $this.removeData(\'textareaHeightAuto\');
            });
        }
    };

    $.fn.textareaHeightAuto = function(method){
        if(methods[method]){
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }else if(typeof method === \'object\' || !method){
            return methods.init.apply(this, arguments);
        }else{
            $.error(\'Method \'+ method + \' does not exist on jQuery.textareaHeightAuto\');
        }
    };

    // 内部方法
    function debug(obj){
        if(window.console && window.console.log){
            window.console.log(obj);
        }
    }

    // 可以适当暴露一些可扩展的方法
    //$.fn.textareaHeightAuto.fun = function(str){};

    // 把默认参数放在外面,使得用户可以在插件之外就修改插件默认设置
    // $.fn.textareaHeightAuto.defaults.bottomHeight = 0;// 修改插件的默认设置
    // $(\'#textarea\').textareaHeightAuto({bottomHeight: 0});// 修改应用插件的当前元素的默认设置
    $.fn.textareaHeightAuto.defaults = {
        maxHeight: 600,
        minHeight: 100,
        bottomHeight: 18,
        eventName: \'paste cut keydown keyup focus blur\'
    };
})(jQuery);

$(document).ready(function(){
    $(\'#J_Txt\').textareaHeightAuto();

    $(\'#J_Btn\').on(\'click\', function(){
        $(\'#J_Txt\').textareaHeightAuto(\'destroy\');
        $(this).attr(\'disabled\', true);
    });
});
</script>
</body>
</html>

 

最后,我在搜索资料的过程中,发现了另外一种类似效果的实现方式,通过设置block元素的contenteditable属性为true来实现,原文请看这里:div模拟textarea文本域轻松实现高度自适应,不失为一种可取的方法,感谢原作者!

 

分类:

技术点:

相关文章:

  • 2021-12-31
  • 2022-01-02
  • 2021-12-04
  • 2021-11-03
  • 2021-12-31
  • 2021-12-31
  • 2021-11-03
猜你喜欢
  • 2021-12-21
  • 2021-12-21
  • 2021-12-31
  • 2021-12-12
  • 2021-12-31
  • 2021-11-03
  • 2021-12-31
相关资源
相似解决方案