自適應高度輸入框(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>轉化為‘\n’;這個時候再用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, '\n')。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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM