文档章节

textarea 高度自适应

l
 lerner
发布于 2016/12/08 18:02
字数 737
阅读 37
收藏 0

前段时间做了一个textarea多行输入框,输入文本自动上顶,到第5行高度固定,且可滑动查看输入内容。(类似微信聊天输入框功能)

开始的思路是取出textarea的value值,然后将这个值放到一个隐藏域(div或者span)中。然后通过比较textarea与隐藏域的width值,来人为的追加"\n",(其实textarea中的折行并没有真正的换行,只有enter键才会触发换行)最后split("\n"),得到一个数组,该数组的长度即为textarea的行数。

试过之后,发现这种方法存在精度上的误差,根本原因是textarea的属性和span不同,比如说字符间距。

项目需求是这样的: 

源文件:


(function (root, factory) {
    'use strict';

//根据项目的实际情况,不同的引入方式
    if (typeof define === 'function' && define.amd) {
        define([], factory);
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.autosize = factory();
    }
}(this, function () {
    function main(ta) {
        if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || ta.hasAttribute('data-autosize-on')) { return; }

        var maxHeight;
        var heightOffset;

        function init() {
            var style = window.getComputedStyle(ta, null); // 详细介绍getComputedStyle函数  http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/

            if (style.resize === 'vertical') {
                ta.style.resize = 'none';
            } else if (style.resize === 'both') {
                ta.style.resize = 'horizontal';
            }

            ta.style.wordWrap = 'break-word';// horizontal overflow 设置为hidden,所以用 word-wrap:break-word 来控制textarea 的宽度是必要的

            // 当 textarea 的 overflow-y:hidden, Chrome/Safari浏览器不会由空格引起页面的回流
            // 可以通过去除滚动条来禁止页面回流
            var width = ta.style.width;
            ta.style.width = '0px';

            ta.offsetWidth;//这里会触发页面回流

            ta.style.width = width;

            maxHeight = style.maxHeight !== 'none' ? parseFloat(style.maxHeight) : false;//未设置最大高度,高度可以一直自适应

            if (style.boxSizing === 'content-box') {
                heightOffset = -(parseFloat(style.paddingTop)+parseFloat(style.paddingBottom));
            } else {
                heightOffset = parseFloat(style.borderTopWidth)+parseFloat(style.borderBottomWidth);
            }

            adjust();
        }

        function adjust() {
            var startHeight = ta.style.height;
            var htmlTop = document.documentElement.scrollTop;
            var bodyTop = document.body.scrollTop;
            var fontSize = parseFloat($('html')[0].style.fontSize) * 1.75 + "px";//行高
            ta.style.height = fontSize;

            var endHeight = ta.scrollHeight+heightOffset;

            if (maxHeight !== false && maxHeight < endHeight) {
                endHeight = maxHeight;
                if (ta.style.overflowY !== 'scroll') {
                    ta.style.overflowY = 'scroll';
                }
            } else if (ta.style.overflowY !== 'hidden') {
                ta.style.overflowY = 'hidden';
            }

            ta.style.height = endHeight +'px';

            // 防止滚动条位置跳跃
            document.documentElement.scrollTop = htmlTop;
            document.body.scrollTop = bodyTop;

            if (startHeight !== ta.style.height) {
                var evt = document.createEvent('Event');
                evt.initEvent('autosize.resized', true, false);
                ta.dispatchEvent(evt);
            }
        }

        //兼容IE9
        if ('onpropertychange' in ta && 'oninput' in ta) {
            ta.addEventListener('keyup', adjust);
        }

        window.addEventListener('resize', adjust);
        ta.addEventListener('input', adjust);

        ta.addEventListener('autosize.update', adjust);

        ta.addEventListener('autosize.destroy', function(style){
            window.removeEventListener('resize', adjust);
            ta.removeEventListener('input', adjust);
            ta.removeEventListener('keyup', adjust);
            ta.removeEventListener('autosize.destroy');

            Object.keys(style).forEach(function(key){
                ta.style[key] = style[key];
            });

            ta.removeAttribute('data-autosize-on');
        }.bind(ta, {
            height: ta.style.height,
            overflow: ta.style.overflow,
            overflowY: ta.style.overflowY,
            wordWrap: ta.style.wordWrap,
            resize: ta.style.resize
        }));

        ta.setAttribute('data-autosize-on', true);
        ta.style.overflow = 'hidden';
        ta.style.overflowY = 'hidden';

        init();
    }

    // IE8不支持
    if (typeof window.getComputedStyle !== 'function') {
        return function(elements) {
            return elements;
        };
    } else {
        return function(elements) {
            if (elements && elements.length) {
                Array.prototype.forEach.call(elements, main);
            } else if (elements && elements.nodeName) {
                main(elements);
            }
            return elements;
        };
    }
}));

引入:

var $dom = this.$dom;
        var oldElHeight = null;
        Array.prototype.forEach.call(document.querySelectorAll('textarea'), function(el){
            oldElHeight = el.style.height;
            el.addEventListener('autosize.resized',function(){
                if ($("#hasSended").html() == "") {//最后一次oldElHeight会一直保存在这里,所以点击发送之后,两边按钮
                                                   //样式会发生错乱,这里用来记录点击发送后,初始化oldElHeight的高度,第一次不会监听。
                    oldElHeight = "";
                }
                var nowElHeight = this.style.height;
                if(!!oldElHeight && !!nowElHeight && oldElHeight != nowElHeight){
                //样式设置
                    var adjust = parseFloat(nowElHeight) - parseFloat(oldElHeight);
                    $dom.speakBottomK.css("height",parseFloat($dom.speakBottomK.css("height")) + adjust + 'px');
                    $dom.speakInputCot.css("height",parseFloat($dom.speakInputCot.css("height")) + adjust + 'px');
                    $dom.toVoiceSwitch.css("margin-top",parseFloat($dom.toVoiceSwitch.css("margin-top")) + adjust + 'px');

                    $dom.sendQues.css("margin-top",parseFloat($dom.sendQues.css("margin-top")) + adjust + 'px');
                }
                oldElHeight = nowElHeight;
                $("#hasSended").html("已发送");//两个js文件 设置隐藏域来判断是否点击了发送按钮
            });
        });

        factory(document.querySelectorAll('textarea'));

 

© 著作权归作者所有

共有 人打赏支持
l
粉丝 0
博文 16
码字总数 3217
作品 0
私信 提问
[贝聊科技]不简单的自适应高度输入框

作者:韩永豪 移动开发部 前端开发工程师 前言 前段时间在项目开发中遇到这样一个需求——文本输入框的高度要随着框内文本所占高度而变化。 下面讲一下实现方案的探索过程。 方案一:利用con...

贝聊科技
08/17
0
0
DWZ框架的HTML扩展

DWZ框架HTML扩展 支持HTML扩展方式来调用DWZ组件 Ajax链接扩展使用方法 示例: 提示窗口 dialog链接扩展使用方法 Html标签扩 展方式示例: 弹出窗口 或 打开窗口一 JS调用方式示例: $.pdialog...

张慧华
2010/04/27
4.2K
0
textarea自适应高度插件--textareaAutoHeight

使用方法: 0. 检查CSS文件中所有textarea的line-height值, 若是纯数字, 给它加上单位em, 如: 1.5em. 否则IE(6|7|8)下插件失效. 1. 加载jQuery库(1.4+) 2. 加载textareaAutoHeight.js 3. 使用...

JE
2011/11/15
2.5K
0
移动端:对高度自适应的输入框说不~

1、textarea: 核心想法: 这个方法在ios上会变得非常奇怪,因为我们使用input进行监听输入的时候,事实上他会把还没输入到屏幕上的文字还在输入法上的文字也计算在里边,所以使用input进行监听...

B_Cornelius
08/27
0
0
拜读及分析Element源码-input组件篇

element-ui源码详细分析以及在其中可以学到的东西整理。(有问题欢迎指正与讨论 也可以来小站逛逛) 首先看生命周期做了什么 外层DIV绑定的一些class 插槽及一些props传入的参数控制外层样式 ...

hollyDysania
09/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Windows / Linux / MacOS 设置代理上网的方法汇总

本文汇总了 Windows / Linux / MacOS 设置代理上网的各种方法,总结如下: 1、设置系统代理(Windows、Linux、MacOS) 2、设置代理插件(Chrome、Chromium、Firefox、Opera、QQ等浏览器) 3、...

sunboy2050
5分钟前
0
0
自定义 Maven 的 repositories

有时,应用中需要一些比较新的依赖,而这些依赖并没有正式发布,还是处于milestone或者是snapshot阶段,并不能从中央仓库或者镜像站上下载到。此时,就需要 自定义Maven的<repositories>。 ...

waylau
今天
1
0
徒手写一个es6代码库

mkdir democd demonpm initnpm install -g babelnpm install -g babel-clinpm install --save-dev babel-preset-es2015-node5 在项目目录创建两个文件夹 functional-playground ......

lilugirl
今天
2
0
linux定位应用问题的一些常用命令,特别针对内存和线程分析的dump命令

1.jps找出进程号,找到对应的进程号后面才好继续操作 2.linux查看进程详细信息 ps -ef | grep 进程ID 3. dump内存信息 Jmap -dump:format=b,file=YYMMddhhmm.dump pid 4.top查看cpu占用信息 ...

noob_chr
今天
1
0
Android TV开发-按键焦点

写在前面 按键焦点过程了解 2.1 dispatchKeyEvent 过程了解 2.2 焦点查找请求过程了解 1.2.1 第一次获取焦点 1.2.3 按键焦点 焦点控制 焦点记忆 应用场景 参考资料 [TOC] 1. 写在前面 工...

冰雪情缘l
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部