看到新浪微博的移动版前端实现的textarea高度自适应,抄一下他的实现源码,如果你感兴趣可以一起学习。
var isMobile = navigator.userAgent.match(/AppleWebKit.*Mobile.*/); var android2_3up = navigator.userAgent.match(/Android ([3-9][._][0-9])/); var ios5up = navigator.userAgent.match(/OS [5-9]_\d[_\d]*/); var clientH = window.innerHeight || document.documentElement.clientHeight; var clientW = window.innerWidth || document.documentElement.clientWidth; var root = window.location.protocol + '//' + window.location.host + '/'; var countShow = document.getElementById("countShow"); var tit = document.getElementById("blog_tit"); var cont = document.getElementById("blog_cont"); var cancel = document.getElementById("cancel"); var submit = document.getElementById("submit"); var clone_tit = document.getElementById("clone_tit"); var clone_cont = document.getElementById("clone_cont"); var titCount = document.getElementById("titCount"); var tipshow = false; var tool = { req: function(options) { if (!options) return; var reqTimeout; var xmlhttp = tool.createStandardXHR() || tool.createActiveXHR(); var type = options.type ? options.type : "get"; xmlhttp.open(type, options.url, options.async ? options.async : true); xmlhttp.setRequestHeader('X-Requested-With', 'xmlHttpRequest'); if (type != "get") { xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } xmlhttp.send(options.data ? (type != "get" ? options.data : null) : null); if (parseInt(options.timeout) > 0) { reqTimeout = setTimeout(function() { xmlhttp.abort(); (options.timeoutFunc) && options.timeoutFunc.call(null); }, parseInt(options.timeout)); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { if ((xmlhttp.status >= 200 && xmlhttp.status < 300) || xmlhttp.status == 304 || (xmlhttp.status == 0 && protocol == 'file:')) { reqTimeout && clearTimeout(reqTimeout); (options.sucFunc) && options.sucFunc.call(null, xmlhttp.responseText); } else { (options.errFunc) && options.errFunc.call(null); } } } }, createStandardXHR: function() { try { return new window.XMLHttpRequest(); } catch (e) {} }, createActiveXHR: function() { try { return new window.ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} }, parseJSON: function(str) { if (window.JSON && window.JSON.parse) { return window.JSON.parse(str); } else { return (new Function("return " + str))(); } }, trim: function(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); }, addClass: function(element, MyclassName) { element.className += (element.className ? " " : "") + MyclassName }, hasClass: function(node, MyClassName) { return RegExp("(^|\\s)" + MyClassName + "(\\s|$)").test(node.className) }, removeClass: function(node, className) { node.className = node.className.replace(RegExp(className + "(\\s|$)"), "") } }; var charCount = { timeout1: null, timeout2: null, overflow: false, disableBtn: function() { if (tool.trim(tit.value) != "" && tool.trim(cont.value) != "") { tool.removeClass(submit, "unable"); } else { if (!tool.hasClass(submit, "unable")) { tool.addClass(submit, "unable") } } }, fixedTit: function(elem, count) { var obj = this.zsdata(elem.value); var number = obj.num; var str = obj.str; /*var number = elem.value.length;*/ if (number > count) { if (isInclient) { /*elem.value = elem.value.substring(0,count);*/ elem.value = str; if (!tipshow) { mblog.showTips("标题不能超过30字"); tipshow = true; } } else { titCount.innerHTML = "-" + (number - count); titCount.style.display = "block"; } } else { titCount.style.display = "none"; } this.disableBtn(); }, zsxz: function(obj, show, num, yujing) { /*var dql = this.zsdata(obj.value).num;*/ dql = obj.value.length; if (dql > num) { if (show) { show.style.display = "block"; show.innerHTML = '<span style="color:red">-' + (dql - num) + '</span>'; this.overflow = true; } } else if (show) { if (num - dql <= yujing) { show.style.display = "block"; show.innerHTML = '<span>' + (num - dql) + '</span>'; } else { show.innerHTML = ""; show.style.display = "none"; } this.overflow = false; } this.disableBtn(); }, zsdata: function(textValue, max) { var res = 0; var arr = ""; var max = max || 30; for (var i = 0, len = textValue.length; i < len; i++) { if (textValue.charCodeAt(i) > 128) { res += 1; } else { res += 0.5; } if (res <= max) { arr += textValue[i]; } } return { num: Math.ceil(res), str: arr }; }, focusTit: function(elem, count) { charCount.timeout1 = setInterval(function() { charCount.fixedTit(elem, count); }, 200); }, blurTit: function() { clearInterval(charCount.timeout1); }, back: function(e) { e = e || window.event; var keycode = e.keyCode ? e.keyCode : (e.which ? e.which : e.charCode); if (keycode == 13) { event.returnValue = false; event.preventDefault(); return false; } } }; var mblog = { showTips: function(msg, CW, CH, notClear) { var h = 45, w = 140, t, l, pop = document.createElement("div"), scrollT = document.body.scrollTop || document.documentElement.scrollTop; document.body.appendChild(pop); pop.id = "showTip"; CH = CH || window.innerHeight || document.documentElement.clientHeight; CW = CW || window.innerWidth || document.documentElement.clientWidth; l = parseInt((CW - w) / 2); t = scrollT + parseInt((CH - h) / 2); /*if (ios5up || android2_3up) {t -= 44;}*/ pop.style.cssText = "top:" + t + "px;left:" + l + "px;"; pop.innerHTML = msg; tit.blur(); if (!notClear) { setTimeout(function() { pop.style.opacity = 0; }, 2000); setTimeout(function() { document.body.removeChild(pop); }, 3000); } return pop; }, showPop: function(msg, callback1, callback2) { var tpl = '<div id="popCont" class="popCont">' + '<div class="popMsg"><span>' + msg.txt + '</span>' + '</div>' + '<div class="popCtrl">' + '<a href="javascript:;" type="leftbtn" class="BtnWhiteLev1 left">' + msg.btn1 + '</a>' + '<a href="javascript:;" type="rightbtn" class="BtnBlueLev1 right">' + msg.btn2 + '</a>' + '</div></div>', CH = clientH || window.innerHeight || document.documentElement.clientHeight, CW = clientW || window.innerWidth || document.documentElement.clientWidth, scrollT = document.documentElement.scrollTop || document.body.scrollTop, body = document.body, h = 166, w = 247; if (document.getElementById("popWrap")) { return; } var pop = document.createElement("div"); body.appendChild(pop); pop.id = "popWrap"; pop.innerHTML = tpl; pop.style.minHeight = (scrollT + CH) + 'px'; var popCont = document.getElementById("popCont"); if (!isMobile) { popCont.style.cssText = 'position:fixed;left:' + parseInt((CW - w) / 2) + 'px;top:' + parseInt((CH - h) / 2) + 'px'; } else { popCont.style.cssText = 'position:absolute;left:' + parseInt((CW - w) / 2) + 'px;top:' + (scrollT + parseInt((CH - h) / 2)) + 'px'; } pop.addEventListener("click", function(e) { var tar = e.target, nodename = tar.nodeName.toLowerCase(); if (tar.nodeType == 3) { tar = tar.parentNode; } if (nodename == 'a') { switch (tar.getAttribute("type")) { case 'leftbtn': setTimeout(function() { callback1.call(tar, e); }, 200); break; case 'rightbtn': setTimeout(function() { callback2.call(tar, e); }, 200); break; default: break; } } body.removeChild(pop); body.removeEventListener("touchmove", noScroll, false); }, false); function noScroll(e) { e.preventDefault(); } body.addEventListener("touchmove", noScroll, false); }, submitBlog: function(e) { var tar = e && (e.target || e.srcElement); var msg = { txt: '网络出现异常,点击“重试”重新加载页面!', btn1: "关闭", btn2: "重试" }; var content = cont.value.replace(/\n+/g, "\n"); if (titCount.style.display == "block") { setTimeout(function() { mblog.showTips("标题不能超过30字", clientW, clientH); }, 500); return; } if (charCount.overflow) { setTimeout(function() { mblog.showTips("正文不能超过10000字", clientW, clientH); }, 500); return; } if (tar) { if (tool.hasClass(tar, "unable")) { return; } else { tool.addClass(tar, "unable"); } } var tt = setTimeout(function() { mblog.showTips("长微博发送中...", clientW, clientH, true); }, 500); tool.req({ url: root + 'mblogDeal/create_longtext', data: "content=" + encodeURIComponent(content) + "&title=" + tit.value + "&" + ajaxPassParams, type: "post", timeout: 5000, timeoutFunc: function() { hidTip(); charCount.disableBtn(); mblog.showPop(msg, mblog.close, mblog.reTry); }, sucFunc: function(data) { hidTip(); try { var res = JSON.parse(data); if (res.ok == 1) { mblog.clear(); charCount.disableBtn(); mblog.goback("sinaweibo://browser/close?needcallback=1"); } else { msg.txt = res.msg ? res.msg : "发布失败"; charCount.disableBtn(); mblog.showPop(msg, mblog.close, mblog.reTry); } } catch (e) { charCount.disableBtn(); mblog.showPop(msg, mblog.close, mblog.reTry); } }, errFunc: function(error) { hidTip(); charCount.disableBtn(); mblog.showPop(msg, mblog.close, mblog.reTry); } }); function hidTip() { clearTimeout(tt); var tip = document.getElementById("showTip"); if (tip) { document.body.removeChild(tip); } } }, cancelSendBlog: function() { var msg = { txt: '你是否想保存该长微博?', btn1: "清空内容", btn2: "保存" }; if (tit.value != "" || cont.value != "") { mblog.showPop(msg, mblog.clear, mblog.saveDraft); } else { mblog.goback('sinaweibo://browser/close'); } }, goback: function(scheme) { if (isInclient) { window.location.href = scheme; /* var ifr = document.createElement('iframe');ifr.src = scheme;ifr.style.display = 'none';document.body.appendChild(ifr);*/ } else { if (scheme == "sinaweibo://browser/close?needcallback=1") { window.location.href = root; } else { window.history.go(-1); } } }, close: function() { /*mblog.goback('sinaweibo://browser/close'); */ }, reTry: function() { mblog.submitBlog(); }, clear: function() { try { if (window.localStorage) { tit.value = ""; cont.value = ""; tit.style.cssText = ""; cont.style.cssText = ""; charCount.disableBtn(); countShow.style.display = "none"; window.localStorage.setItem("H5_LONGTEXT_DRAFT_TITLE", ""); window.localStorage.setItem("H5_LONGTEXT_DRAFT_CONTENT", ""); } } catch (e) {} mblog.goback('sinaweibo://browser/close'); }, saveDraft: function(eve) { try { if (window.localStorage) { console.log(tit.value); window.localStorage.setItem("H5_LONGTEXT_DRAFT_TITLE", tit.value); window.localStorage.setItem("H5_LONGTEXT_DRAFT_CONTENT", cont.value); } } catch (e) {} if (eve) { mblog.goback('sinaweibo://browser/close'); } }, loadBlog: function() { try { if (window.localStorage) { var ls_tit = window.localStorage.getItem("H5_LONGTEXT_DRAFT_TITLE"); var ls_cont = window.localStorage.getItem("H5_LONGTEXT_DRAFT_CONTENT"); if (ls_tit) { tit.value = ls_tit; } if (ls_cont) { cont.value = ls_cont; } } } catch (e) {} autoTextarea(tit, clone_tit, 30); autoTextarea(cont, clone_cont, 10000); if (!isInclient) { charCount.fixedTit(tit, 30); } } }; var autoTextarea = function(elem, clone, count, extra, maxHeight) { extra = extra || 0; var interval; var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window, isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'), addEvent = function(type, callback) { elem.addEventListener ? elem.addEventListener(type, callback, false) : elem.attachEvent('on' + type, callback); }, getStyle = elem.currentStyle ? function(name) { var val = elem.currentStyle[name]; if (name === 'height' && val.search(/px/i) !== 1) { var rect = elem.getBoundingClientRect(); return rect.bottom - rect.top - parseFloat(getStyle('paddingTop')) - parseFloat(getStyle('paddingBottom')) + 'px'; }; return val; } : function(name) { return getComputedStyle(elem, null)[name]; }, minHeight = parseFloat(getStyle('height')); elem.style.resize = 'none'; var change = function() { var scrollTop, height, padding = 0, style = elem.style; if (elem._value === elem.value) return; elem._value = elem.value; clone.value = elem.value; if (count > 30) { charCount.zsxz(elem, countShow, count, 5); } mblog.saveDraft(false); if (!isFirefox && !isOpera) { padding = parseInt(getStyle('paddingTop')) + parseInt(getStyle('paddingBottom')); }; if (clone.scrollHeight > minHeight && (clone.scrollHeight - padding) + "px" != style.height) { if (maxHeight && clone.scrollHeight > maxHeight) { height = maxHeight - padding; style.overflowY = 'auto'; } else { height = clone.scrollHeight - padding; style.overflowY = 'hidden'; }; style.height = height + 'px'; if (count > 30) { scrollTop = document.body.scrollTop || document.documentElement.scrollTop; scrollTop += parseInt(style.height) - elem.currHeight; document.body.scrollTop = scrollTop; document.documentElement.scrollTop = scrollTop; } elem.currHeight = parseInt(style.height); }; }; /*addEvent('propertychange', change);addEvent('input', change);addEvent('propertychange', change);addEvent('input', change);addEvent('focus', change);*/ addEvent("focus", function() { elem.interval = setInterval(function() { change(); }, 200); }); addEvent("blur", function() { clearInterval(elem.interval); }); change(); }; mblog.loadBlog(); cancel.onclick = mblog.cancelSendBlog; submit.onclick = mblog.submitBlog; tit.onfocus = function() { charCount.focusTit(tit, 30); }; tit.onblur = function() { charCount.blurTit(); }; tit.onkeypress = charCount.back; /*顶导航fixed*/ (function() { var isSafari = /constructor/i.test(window.HTMLElement); var Jheader = document.getElementById("J-header"); if (ios5up || android2_3up) { if (isSafari) { return; } Jheader.style.position = "fixed"; Jheader.style.top = "0px"; Jheader.style.left = "0px"; document.getElementById("blog_wrap").style.marginTop = "44px"; } /*事件处理,聚焦正文时,隐藏标题。滑动时取消正文焦点,否则滚动不流畅*/ if (isMobile && !isSafari) { window.addEventListener("touchstart", function(e) { var touch = e.touches[0] || e.changedTouches; startY = touch.pageY; }, false); window.addEventListener("touchmove", function(e) { var touch = e.touches[0] || e.changedTouches; if (touch.pageY - startY > 20) { cont.blur(); } }, false); } })(); window.onload = function() { clientH = window.innerHeight || document.documentElement.clientHeight; clientW = window.innerWidth || document.documentElement.clientWidth; }
HTML
<body> <nav class="J-header sub-header" id="J-header"><a id="cancel" class="back-header left" href="javascript:;" title="">取消</a><a id="submit" class="BtnLev4 right unable" href="javascript:;">发送</a><span>编辑长微博</span></nav> <div class="blog_wrap" id="blog_wrap"> <h2 id="titwrap"><textarea id="clone_tit"></textarea><textarea id="blog_tit" placeholder="标题(必填)" ></textarea><div id="titCount" style="display:none;"></div></h2> <div id="contwrap"> <textarea id="clone_cont"></textarea> <textarea id="blog_cont" placeholder="正文(必填)"></textarea> </div> </div> <div id="countShow" class="countShow"></div> </body>
CSS
html { position: relative; } body { margin: 0; padding: 0; } a { text-decoration: none; } .blog_wrap { margin: 0px 15px 0 18px; color: #333; overflow: hidden; } #titwrap, #contwrap { position: relative; } #contwrap { margin: 8px 0 10px 0; } #clone_tit, #clone_cont { position: absolute; top: 0; left: 0; z-index: -1; } .blog_wrap textarea { display: block; outline: none; resize: none; padding: 0; margin: 0; overflow: hidden; width: 100%; border: 0px solid; word-wrap: break-word; word-break: break-all; width: 100%; border: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .blog_wrap h2 { border-bottom: 1px solid #dedede; width: 100%; margin: 0; padding: 0; overflow: hidden; } #clone_tit, #clone_cont { visibility: hidden; } .blog_wrap h2 #blog_tit, #clone_tit { height: 20px; font-size: 18px; line-height: 1.3em; margin: 10px 0 8px 0; } .blog_wrap #blog_cont, #clone_cont { height: 200px; font-size: 16px; } .countShow { text-align: right; width: 100%; height: 20px; text-align: right; } .countShow span { margin: 0 18px; position: relative; top: -10px; font-size: 15px; } .BtnWhiteLev1 { border: #c5c6c6 solid 1px; border-color: #c5c6c6 #bdbebe #b6b6b6; color: #5d5d5d; text-align: center; background-color: #f2f2f2; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e8e8e8), color-stop(.92, #dfdfdf)); background-image: -moz-linear-gradient(#f2f2f2 0%, #dfdfdf 92%, #e8e8e8 100%); background-image: -o-linear-gradient(#f2f2f2 0%, #dfdfdf 92%, #e8e8e8 100%); background-image: -ms-linear-gradient(#f2f2f2 0%, #dfdfdf 92%, #e8e8e8 100%); background-image: linear-gradient(to bottom, #f2f2f2 0%, #dfdfdf 92%, #e8e8e8 100%); -webkit-border-radius: 5px; border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .06), inset 0 1px rgba(255, 255, 255, .56); box-shadow: 0 1px 2px rgba(0, 0, 0, .06), inset 0 1px rgba(255, 255, 255, .56); text-shadow: 0 1px 0 rgba(255, 255, 255, .65); } .BtnWhiteLev1:visited { color: #5d5d5e; } .BtnBlueLev1 { border: #447dc4 solid 1px; border-color: #447dc4 #3f72b1 #39679f; color: #fff; text-align: center; background-color: #508ed8; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#508ed8), to(#5088cc), color-stop(.92, #457ab8)); background-image: -moz-linear-gradient(#508ed8 0%, #457ab8 92%, #5088cc 100%); background-image: -o-linear-gradient(#508ed8 0%, #457ab8 92%, #5088cc 100%); background-image: -ms-linear-gradient(#508ed8 0%, #457ab8 92%, #5088cc 100%); background-image: linear-gradient(to bottom, #508ed8 0%, #457ab8 92%, #5088cc 100%); -webkit-border-radius: 5px; border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2), inset 0 1px #609be3; box-shadow: 0 1px 2px rgba(0, 0, 0, .2), inset 0 1px #609be3; text-shadow: 0 1px 0 rgba(0, 0, 0, .35); } .BtnBlueLev1:visited { color: #fffffe; } #popWrap { position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: 999; text-align: center; background: rgba(0, 0, 0, .6); z-index: 999; } #popWrap .popCont { width: 248px; height: 166px; margin: auto; background: #f8f8f8; border-top: 3px solid #fd9436; } #popWrap a { display: block; width: 98px; height: 33px; line-height: 33px; } #popWrap .popMsg { height: 100px; line-height: 100px; font-size: 15px; font-weight: bold; } #popWrap .popMsg span { line-height: 1.5em; margin: 0 18px; display: inline-block; text-align: center; vertical-align: middle; } #popWrap .popCtrl { border-top: 1px solid #e7e7e7; padding: 15px 18px; overflow: hidden; } #showTip { width: 140px; height: 45px; line-height: 45px; position: absolute; text-align: center; border-radius: 8px; font-weight: bold; font-size: 12px; color: #fff; background: rgba(0, 0, 0, .6); -webkit-transition: opacity 0.4s ease-out; } #titCount { font-size: 15px; color: red; text-align: right; position: relative; top: -6px; font-weight: normal; margin: 0 5px; } .sub-header { background: #f8f8f8; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f8f8f8), to(#e8e8e8)); background-image: -moz-linear-gradient(#f8f8f8, #e8e8e8); background-image: -o-linear-gradient(#f8f8f8, #e8e8e8); background-image: -ms-linear-gradient(#f8f8f8, #e8e8e8); background-image: linear-gradient(to bottom, #f8f8f8, #e8e8e8) } .sub-header { position: relative; z-index: 1; border-bottom: #bababa solid 1px; height: 43px; width: 100%; text-align: center; -wekbit-box-shadow: inset 0 -1px 0 #f4f4f4, 0 1px 2px #c3c3c3; box-shadow: inset 0 -1px 0 #f4f4f4, 0 1px 2px #c3c3c3 } .sub-header a { margin: 6px 8px; height: 27px; line-height: 27px; font-size: .75rem; } .sub-header .back-header { overflow: hidden; margin: 10px 13px 0; width: 24px; height: 25px; line-height: 25px; text-indent: -300px; } .sub-header span { font-size: 1.25rem; line-height: 43px; display: inline-block; max-width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .left { float: left; left: 8px; -webkit-transform-origin: 0 0; } .right { float: right; right: 8px; -webkit-transform-origin: 100% 0; } .back-header { background-image: url(http://u1.sinaimg.cn/upload/h5/img/v5/new-page-icon_20130717.png); } @media only screen and (-webkit-min-device-pixel-ratio: 2) { .back-header { background-image: url(http://u1.sinaimg.cn/upload/h5/img/v5/new-page-icon_2x_20130717.png); } } .back-header { background-position: 0 -263px; background-repeat: no-repeat; background-size: 24px auto; } .BtnLev4 { border: #bdbcbc solid 1px; border-color: #bdbcbc #b5b5b5 #aeaeae; padding: 0 10px; color: #383838; background: #ececec; background: -webkit-gradient(linear, left top, left bottom, from(#ececec), to(#dbdbdb)); background: -moz-linear-gradient(#ececec, #dbdbdb); background: -o-linear-gradient(#ececec, #dbdbdb); background: -ms-linear-gradient(#ececec, #dbdbdb); background: linear-gradient(to bottom, #ececec, #dbdbdb); -webkit-border-radius: 3px; border-radius: 3px; text-shadow: 0 1px #fff; -webkit-box-shadow: 0 1px 0 rgba(248, 248, 248, .65) inset, 0 1px 0 rgba(255, 255, 255, .35); box-shadow: 0 1px 0 rgba(248, 248, 248, .65) inset, 0 1px 0 rgba(255, 255, 255, .35) } .BtnLev4:visited { color: #383839 } .BtnLev4.unable { color: #ccc } .BtnLev4.unable:visited { color: #cccccd } .blog_wrap { margin: 0px 12px 0 12px; } .countShow span { margin: 0 13px; }
from:https://m.weibo.cn/mblog/longMblog