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);
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/wj19940520/p/10232396.html
Copyright © 2011-2022 走看看