zoukankan      html  css  js  c++  java
  • 自适应高度输入框(contenteditable/textarea)

     
    一、用div模拟textarea

    div模拟输入域可以根据输入内容自动伸缩,而input和textarea输入内容较多时,高度固定,内容会显示不全。

    1.坑1(IOS端无法输入)

    在取消全局默认样式的时候,由于代码加了-webkit-user-select: none(设置或检索是否允许用户选中文本),只要在当前div上设置-webkit-user-select: text就可以输入了。

    2.坑2(IOS端无法获取焦点或者只有双击后才可以获取焦点)

    在移动端,为了解决300s延迟的问题,我的代码引入了fastclick库,导致点击时会执行preventDefault防止向上冒泡,具体原因看https://blog.csdn.net/soft_z1302/article/details/83104461,所以只要在div上加class="needsclick"就可以了。

    3.坑3(提示文字)

    div不像input那样,有placeholder属性,要实现这样的效果,得这么写:

    <div class="editdiv needsclick" contenteditable="true" placeholder="请输入未进店备注"></div>
    
    <style>
        .editdiv {
         -webkit-user-select:text;
        }
        .editdiv:empty::before {
        content: attr(placeholder);
        color: #999;
        }
        .editdiv:focus::before {
        content: none;
        }
    </style>

     4.坑4(换行加div)

    contenteditable="true"时,如果输入文本内容,换行时文本自动被div包裹,最后一行如果换行了,会强行包裹一个br,保存时报错,那么将true改为 “ plaintext-only ” ,就解决了被div包裹的问题。

    此时安卓是没啥问题了......,但是ios还有问题,你会发现ios将空格转义为了'&nbsp;',并且<br>仍旧还是<br>,都知道trim()方法可以去除字符串两边的空格(' '),这个空格(' ')跟'&nbsp;'是不一样的,所以要想在ios中去除两边空格,必须先将‘&nbsp;’转化为(' '),然后再来看<br>,其实跟上面方法是一致的,咱们先将<br>转化为‘ ’;这个时候再用trim方法,就可以将字符串两头的空格和换行去掉了;到此为止你可能认为已经完全OK了,no no no ,我们测试又发现一bug,就是IOS当你在div中输入内容过多,换行较多时,html()里居然还有<div></div>,我真的是一脸懵逼!!!plaintext-only属性为啥会出现这种情况呢??我也没捣鼓清楚。那么现在唯一的解决办法是将文字中的div标签全部替换掉。

    <div class="editdiv needsclick" contenteditable="plaintext-only" placeholder="请输入未进店备注"></div>
    if (browser.versions.ios) {
      str=str.replace(/&nbsp;/g, ' ').replace(/<br>/g, '
    ')。replace(/<div>/g, '').replace(/</div>/g, '').trim();
    } else {
      str= str.trim();
    }

    var replace = /<div.*?>(.*?)</div>/g;
     

    详细看这里https://www.zhangxinxu.com/wordpress/2016/01/contenteditable-plaintext-only/

    5.坑5(如果div在页面底部,当div获取焦点时,ios中键盘覆盖了可输入区域,需要手动向下滑才能显示)

    所以在ios下,需要获取键盘的高度(由于各种输入法和中英文切换时,键盘高度不一致),但是键盘高度又无法通过js或者html获取,所以我只能是写了一个大约值(200/250)

    /*页面最底部的备注获取焦点时被软键盘遮挡*/
            if (browser.versions.ios && $("body").height() - $(this).offset().top < 200) {
                 window.scrollTo(0, $(window).scrollTop() + 200);
            }

    对于这个问题,我用textarea试了一下,发现焦点能自动出现在可视区域内。

    二、实时计算textarea的高度,给textarea给自适应的高度

    <style type="text/css"> 
    h2{
            text-align: center;
            margin:50px auto;
        }
    .textarea { 
        display: block;
        margin:0 auto;
        overflow: hidden; 
        width: 100%; 
        font-size: 14px;
        height: 18px; 
        line-height: 1.4; 
        margin:10px auto;
        outline: 0 none;
        border-color: rgba(82, 168, 236, 0.8);
        box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
    }
    }
    
    </style> 

    <body> <h2>文本框根据输入内容自适应高度</h2> <textarea id="textarea" class="textarea" placeholder="回复内容" style="resize: none; height: 30px; overflow-y: hidden;"></textarea> <textarea id="textarea1" class="textarea" placeholder="回复内容1" style="resize: none; height: 30px; overflow-y: hidden;"></textarea> <textarea id="textarea2" class="textarea" placeholder="回复内容2" style="resize: none; height: 30px; overflow-y: hidden;"></textarea> </body>

    <script>
    $(".textarea").textFocus();
    </script>

     从网上搜到相关代码,重新缕了一下:

    ;(function($){
             $.fn.textFocus=function(options){
                 var defaults={
                       elem:"",
                     extra:0,
                     maxHeight:"auto"
                 }
                 var options=$.extend(defaults,options);
                 //兼容浏览器
                 var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window;
                 var isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera');
                   $(this).each(function(){
                     var _this=this;
                     options.elem=_this;
                     /*点击事件兼容性*/
                     function addEvent(type,callback){
                         _this.addEventListener?_this.addEventListener(type,callback,false):_this.attachEvent("on"+type,callback);
                     }
                     
                     function getStyleDifference(name){
                         var val=_this.currentStyle[name];
                         if(name==="height"&&val.search(/px/i)!==1){
                             var react=_this.getBoundingClientRect();
                             return react.bottom-react.top-parseFloat(getStyle("paddingTop"))-parseFloat(getStyle("paddingBottom"))+"px";
                         }
                         return val;
                     };
                     
                     
                     function getStyle(name){
                         return _this.currentStyle?getStyleDifference(name):getComputedStyle(_this,null)[name];
                     }
                     
                     var minHeight=parseFloat(getStyle("height"));
                     
                     function change(){
                         var scrollTop,height,padding=0,style=_this.style;
                         if(_this._length===_this.value.length) return;
                         _this._length=_this.value.length;
                         if(!isFirefox && !isOpera){
                             padding = parseInt(getStyle("paddingTop"))+parseInt(getStyle("paddingBottom"));
                         }
                         scrollTop=document.body.scrollTop||document.documentElement.scrollTop;
                         _this.style.height=minHeight+"px";
                         if(_this.scrollHeight>minHeight){
                             if(options.maxHeight&&_this.scrollHeight>options.maxHeight){
                                 height=options.maxHeight-padding;
                                 style.overflowY='auto';
                             }else{
                                 height=_this.scrollHeight-padding;
                                   style.overflowY="hidden";
                             }
                             style.height=height+options.extra+'px';
                             if(_this.currHeight!=undefined&&_this.currHeight!="NaN"){
                                 scrollTop+=parseInt(style.height)-_this.currHeight;
                             }else{
                                 scrollTop+=parseInt(style.height);
                             }
                             
                             document.body.scrollTop=scrollTop;
                             document.documentElement.scrollTop=scrollTop;
                             _this.currHeight=parseInt(style.height);
                         }
                     }
                     
                     addEvent("propertychange",change);
                     addEvent("input",change);
                     addEvent("focus",change);
                     change();
                     
                })
             }
         })(jQuery);
  • 相关阅读:
    牌型种数|2015年蓝桥杯B组题解析第七题-fishers
    加法变乘法|2015年蓝桥杯B组题解析第六题-fishers
    九数组分数|2015年蓝桥杯B组题解析第五题-fishers
    [Oracle]Oracle学习小结(1)
    [Oracle]Oracle数据库任何用户密码都能以sysdba角色登入
    【oracle】Enterprise Manager 无法连接到数据库实例。下面列出了组件的状态---个人解决方案
    从两个字符串中找出最大公共子字符串
    Java学习小结(1)-数组的创建与传参
    php学习日志(5)-解决Windows Live Writer错误:WindowsLive.Writer.CoreServices.HttpRequestHelper的类型初始值设定发生异常
    php学习日志(4)-The mbstring extension is missing. Please check your PHP configuration错误及解决方法
  • 原文地址:https://www.cnblogs.com/wj19940520/p/10232396.html
Copyright © 2011-2022 走看看