html的原生自定义键盘(数字版)

时间: 2018-05-03阅读: 1082标签: 键盘

前言:

前端现在很多时候,由于要限制文本的输入格式(这里指只允许输入数字),常常需要使用到自定义键盘。自定义键盘难免涉及到复用,资源占用等问题,有时候还会由于封装不好导致事件混乱、或者由于动画效果没实现好导致看上去很尴尬。。。等这个那个的。本人根据这些情况,小做了一个原生的数字版键盘,希望可以给大家一点灵感,代码不好之处,敬请谅解!!!


正文:

正文,也叫代码解析,是程序员学习最快最有效的方式。。。。。

keyBoard.js(封装的方法就在这里了,纯原生,不依赖,当然,IE9+哈,建议只扩展,不修改。当然,我写的不好的地方随便改,改了留个言帮我纠正一下。android后退键关闭的话,这里是没写的,需要cordova之类的插件支持才行)

(function(window, storage, undefined) {
    'use strict'

    window.keyBoard = function() {
        var keyBoarddiv, keyBoard, commit, dialog, input, label, span, table, tbody, tr, td;
        var keyBoardClick, keyBoarddivClick, keyBoardTranstionEnd;
        var body = document.getElementsByTagName("body")[0];
        var keyModels = {
            SIMPLE: {
                COLS: 3,
                WIDTH: '33.3%',
                TYPE: 1,
                KEYS: [7, 8, 9, 4, 5, 6, 1, 2, 3, '-', 0, '<']
            },
            PLUS: {
                COLS: 4,
                WIDTH: '25%',
                TYPE: 1,
                KEYS: [7, 8, 9, 'C', 4, 5, 6, '↑', 1, 2, 3, '↓', '-', 0, '.', '<']
            }
        };

        var transtion;
        var currModel;
        var closeCB;
        var inputText = "",
            currText, fixed = 0,
            offset = -1;
        var popEvent = function() {
            this.closeKeyBoard(true);
        };
        var statusUtils = function() {
            var changing = false;
            return {
                setChanging: function(status) {
                    changing = status;
                },
                getChanging: function() {
                    return changing;
                }
            }
        }();

        return {
            openKeyBoard: openKeyBoard,
            closeKeyBoard: closeKeyBoard,
            keyModels: keyModels
        };

        function openKeyBoard(notice, initNumber, model, callbackEvery, callbackLast, openCallback, closeCallback) {
            if(statusUtils.getChanging()) {
                return false;
            }
            statusUtils.setChanging(true);
            var _this = this;

            /*****   处理返回事件    *******/
            if(window.history && window.history.pushState) {
                window.history.pushState(null, null, document.URL);
                window.addEventListener("popstate", popEvent.bind(_this), false);
            }
            /*****   处理返回事件结束    *******/

            // 参数置换
            if(typeof model === "function") {
                closeCallback = openCallback;
                openCallback = callbackLast;
                callbackLast = callbackEvery;
                callbackEvery = model;
                model = undefined;
            }

            // 关闭事件回调赋值
            closeCB = closeCallback;

            // UI
            model = model || keyModels.SIMPLE;
            if(!keyBoardDiv || model !== currModel) {
                inputText = "";
                currModel = model;

                if(keyBoardDiv) {
                    body.removeChild(keyBoardDiv);
                }

                // 键盘上的对话框
                dialog = document.createElement("DIV");
                label = document.createElement("DIV");
                span = document.createElement("SPAN");
                input = document.createElement("SPAN");
                commit = document.createElement("BUTTON");

                dialog.className = 'qs-keyBoard-dialog';
                commit.innerhtml = "完成";
                input.className = "qs-inset-input";
                input.style.textAlign = 'center';
                label.appendChild(input);
                label.appendChild(commit);
                dialog.appendChild(span);
                dialog.appendChild(label);

                keyBoardDiv = document.createElement("DIV");
                keyBoardDiv.className = "qs-key-board-bg";

                // 键盘部分
                keyBoard = document.createElement("DIV");
                table = document.createElement("TABLE");
                tbody = document.createElement("TBODY");
                keyBoard.className = "qs-key-board";
                keyBoard.id = 'qs-keyboard-id';
                table.border = '0';
                for(var i = 0; i < currModel.KEYS.length; i++) {
                    if(i % currModel.COLS === 0) {
                        tr = document.createElement("TR");
                    }
                    if(currModel.KEYS[i] || currModel.KEYS[i] === 0) {
                        td = document.createElement("TD");
                        td.style.width = currModel.WIDTH;
                        if(typeof(currModel.KEYS[i]) === "object") {
                            currModel.KEYS[i].icon ? td.className = currModel.KEYS[i].icon : td.innerhtml = currModel.KEYS[i].text;
                            currModel.KEYS[i].rows && td.setAttribute('rowspan', currModel.KEYS[i].rows);
                            td.setAttribute("qs-data-value", currModel.KEYS[i].text);
                        } else {
                            td.innerHTML = currModel.KEYS[i];
                            td.setAttribute("qs-data-value", currModel.KEYS[i]);
                        }
                        tr.appendChild(td);
                    }
                    if(i % currModel.COLS === currModel.COLS - 1) {
                        tbody.appendChild(tr);
                    }
                }
                table.appendChild(tbody);
                keyBoard.appendChild(dialog);
                keyBoard.appendChild(table);
                keyBoardDiv.appendChild(keyBoard);
                body.appendChild(keyBoardDiv);
            }

            input.innerHTML = inputText = (initNumber + "") || "";
            span.innerHTML = notice || '';

            //预移除事件(快速点击时动画误差)
            transtion = whichTransitionEvent(keyBoardDiv);//判断当前使用的事件类型
            if(keyBoardClick) {
                keyBoard.removeEventListener("click", keyBoardClick);
                keyBoardDiv.removeEventListener("click", keyBoardDivClick);
                keyBoardDiv.removeEventListener(transtion, keyBoardTranstionEnd);
            }

            // 监听事件
            keyBoardDivClick = function() {
                inputText = inputText === '-' ? '' : inputText;
                callbackLast && callbackLast(inputText ? Number(inputText) : '');
                _this.closeKeyBoard();
            };

            keyBoardClick = function(e) {
                switch(e.target.nodeName) {
                    case 'TD':
                        e.stopPropagation();
                        e.preventDefault();
                        doKeys(e);
                        break;
                    case 'BUTTON':
                        break;
                    default:
                        e.stopPropagation();
                        e.preventDefault();
                        break;
                }
            };
            
            keyBoardTranstionEnd = function() {
                statusUtils.setChanging(false);
                openCallback && openCallback();
            };

            function doKeys(e) {
                currText = e.target.getAttribute("qs-data-value");
                inputText = inputText === '0' ? '' : inputText;
                switch(currText) {
                    case '-':
                        inputText = inputText.indexOf('-') === -1 ? '-' + inputText : inputText.slice(1);
                        break;
                    case '.':
                        inputText = inputText ? inputText === '-' ? inputText = '-0.' : (inputText.indexOf('.') === -1 ? inputText + '.' : inputText) : '0.';
                        break;
                    case '<':
                        inputText = inputText ? inputText.slice(0, -1) : '';
                        break;
                    case 'C':
                        inputText = '';
                        break;
                    case '↑':
                        inputText = calcNumber(inputText, 2);
                        break;
                    case '↓':
                        inputText = calcNumber(inputText, 1);
                        break;
                    default:
                        inputText = inputText === '-0' ? '-' : inputText;
                        inputText += currText;
                        break;
                }
                input.innerHTML = inputText;
                callbackEvery && callbackEvery(inputText ? Number(inputText) : '');
            }

            function calcNumber(str, type) {
                str = str === '-' ? "0" : str;
                offset = str.indexOf('.');
                fixed = offset > -1 ? str.length - offset - 1 : 0;
                str = Math.round(Number(str) * Math.pow(10, fixed) + Math.pow(10, fixed) * Math.pow(-1, type)) / Math.pow(10, fixed);
                return str.toString();
            }

            // 注册监听事件
            keyBoard.addEventListener("click", keyBoardClick, false);
            keyBoardDiv.addEventListener("click", keyBoardDivClick, false);
            keyBoardDiv.addEventListener(transtion, keyBoardTranstionEnd, false);

            keyBoardDiv.className = "qs-key-board-bg";
            setTimeout(function(){
                keyBoardDiv.className = "qs-key-board-bg qs-keyboard-up";                
            });
        }

        /**
         * 关闭键盘
         * @param doBack 是否执行一次回退(不是导航栏返回触发的需要执行一次回退)
         */
        function closeKeyBoard(doBack) {
            if(statusUtils.getChanging()) {
                return false;
            }
            statusUtils.setChanging(true);
            
            // 动画完成事件
            var closeKeyBoardTranstionEnd = function() {
                keyBoardDiv.className = "qs-key-board-bg display-none";
                statusUtils.setChanging(false);
                keyBoardDiv.removeEventListener(transtion, closeKeyBoardTranstionEnd);
                
                // 键盘关闭回调事件
                closeCB && closeCB();
            };
            keyBoardDiv.addEventListener(transtion, closeKeyBoardTranstionEnd, false);
            keyBoardDiv.className = "qs-key-board-bg";
            inputText = '';
            
            // 处理回退事件
            if(window.history && window.history.pushState) {
                if(!doBack) {
                    window.history.back();
                }
                window.removeEventListener("popstate", popEvent);
            }
            // 移除监听事件
            keyBoard.removeEventListener("click", keyBoardClick);
            keyBoardDiv.removeEventListener("click", keyBoardDivClick);
            keyBoardDiv.removeEventListener(transtion, keyBoardTranstionEnd);
        }

        function whichTransitionEvent(el) {
            var transitions = {
                'transition': 'transitionend',
                'OTransition': 'oTransitionEnd',
                'MozTransition': 'transitionend',
                'WebkitTransition': 'webkitTransitionEnd'
            }

            for(var t in transitions) {
                if(el.style[t] !== undefined) {
                    return transitions[t];
                }
            }
        }
    }();
})(window, window.localStorage)


keyboard.css (这是键盘的样式文件,随便改)  

.qs-key-board-bg {
    position: absolute;
    pointer-events: painted;
    width: 100%;
    left: 0;
    top: 100%;
    height: 100%;
    transition: top .3s ease;
    -webkit-transition: top .3s ease;
    z-index: 999;
    -moz-user-select: none;
    -ms-touch-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
}

.qs-key-board {
    background-color: white;
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
}

.qs-keyBoard-dialog {
    padding: 5px 10px;
    background-color: white;
    box-shadow: inset 0px 5px 15px #efefef;
}

.qs-keyBoard-dialog > div {
    display: flex;
    height: 30px;
}

.qs-keyBoard-dialog > div > button {
    width: 6em;
}

.qs-keyBoard-dialog > span {
    font-size: 14px;
    display: block;
    padding: 2px;
    color: #999999;
    white-space: nowrap;
    text-overflow:ellipsis;
    overflow:hidden;
}

.qs-key-board > table {
    width: 100%;
    background-color: #efefef;
    border-spacing: 6px;
    border-collapse: separate;
}

.qs-key-board tr{
    height: 3.5rem;
}

.qs-key-board td {
    width: 33.3%;
    border: solid 1px #dedede;
    border-radius: 6px;
    -webkit-border-radius: 6px;
    font-size: 2rem;
    text-align: center;
    vertical-align: middle;
    background-color: white;
}

.qs-key-board td:active{
    background-color: #dedede;
}

.qs-keyboard-up {
    top: 0%;
}

.qs-inset-input {
    position: relative;
    display: inline-block;
    border-radius: 3px;
    -webkit-border-radius: 3px;
    margin-right: 10px;
    border: none;
    font-size: 18px !important;
    width: 100%;
    height: 30px !important;
    line-height: 30px;
    background-color: rgb(238,238,238) !important;
}

.qs-keyboard-switch {
    position: absolute;
    overflow: hidden;
    pointer-events: painted;
    right: -120px;
    z-index: 1000;
    margin-bottom: -7px;
    transition: right 300ms ease;
    -webkit-transition: right 300ms ease;
}

.qs-keyboard-switch:before{
    position: absolute;
    z-index: 1;
    right: 25px;
    top:12px;
    font-size: 20px;
    color: white;
    line-height: 20px;
    width: 20px;
    height: 20px;
}

.qs-keyboard-switch-show {
    right: 0px;
}

.qs-input-dialog {
    width: 100%;
    z-index: 999;
    position: absolute;
    bottom: 0;
    margin-bottom: -61px;
    transition: margin-bottom 300ms ease;
}

.qs-input-dialog-show {
    margin-bottom: 0px;
}


index.html(调用的例子,参考用) 

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title></title>
        <link rel="stylesheet" href="css/keyBoard.css" />
        <style>
            html, body{
                height: 100%;
                padding: 0;
                margin: 0;
                overflow: hidden;
            }
            
            span#input{
                display: inline-block;
                border-bottom: solid 1px green;
                width: 200px;
                height: 30px;
                line-height: 30px;
                margin: 20px;
                background-color: #EFEFEF;
            }
        </style>
    </head>

    <body>
        <span id="input" onclick="openKeyBoard(this)"></span>
    </body>
    <script>
        function openKeyBoard(_this){
            keyBoard.openKeyBoard('请输入数字', _this.innerText, keyBoard.keyModels.PLUS, function(number){
                _this.innerText = number;
            });
        }
    </script>
    <script type="text/JavaScript" src="js/keyBoard.js" ></script>
</html>


 

后语:

对了,我这个键盘放在body下的,所以body应该是高度100%,宽度充满,并且又overflow:hidden的,这部分观众老爷自行调整,position改fixed也是可以的。

来源:https://www.cnblogs.com/longhuangv5/archive/2018/05/02/8979603.html


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/728

关闭

可能这些是你想要的H5软键盘兼容方案

最近一段时间在做 H5 聊天项目,踩过其中一大坑:输入框获取焦点,软键盘弹起,要求输入框吸附(或顶)在输入法框上。需求很明确,看似很简单,其实不然。从实验过一些机型上看,发现主要存在以下问题:

vue 键盘操作事件

当按键盘enter键和键盘左右键时,左右切换页面卡片并读取卡片上的信息,Internet Explorer/Chrome 浏览器使用 event.keyCode 取回被按下的字符,而 Netscape/Firefox/Opera 等浏览器使用 event.which

vue 自定义 键盘监听事件

vue 自己的键盘监听事件 需要有焦点才能使用,比如input button等 如果我们想在整个页面使用的话 可以使用js原生的监听事件

js键盘事件以及键盘事件拦截

onkeydown: 按下键盘时触发;onkeypress: 按下有值的键时触发,注意: onkeypress按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触发对于有值的键,按下时先触发 keydown 事件,再触发这个事件

vue中监听返回键

在项目中,我们常常有需求,当用户在填写表单时,点击返回的时候,我们希望加一个弹窗,确认离开吗,确认将保存为草稿;利用 H5的 pushstate(个人理解为增加页面栈)特性与onpopup事件

微信小程序仿input组件、虚拟键盘

仿照微信支付界面,金额输入框不能用input;要有光标,点击输入框调起虚拟键盘,点击输入框以外的地方隐藏输入框;第一个输入的是小数点要补全,比如:第一个输入的是小数点,则输入框显示为 0. ;

通过focusout事件解决IOS键盘收起时界面不归位的问题

今天在开发一个移动端的 H5 页面时,遇到了 IOS 上键盘收起时界面无法归位的问题。下面详细描述下问题和症状:出问题的页面是一个表单结构。即类似于一个 div 下有4个 input 表单的结构

为什么程序员使用电脑时,很少使用鼠标,只需要键盘就能工作?

现在很多人在使用电脑的时候会特别依赖鼠标,因为使用鼠标操作会比较方便,身边有程序员的人可能会疑惑为什么他们在使用电脑的时候,不需要鼠标,只需要一个键盘就能工作了呢?

移动端调起软键盘导致 position:fixed 偏移

app内打开H5页面,页面包含input输入框,点击input调起软键盘,输入完成点击下方提交按钮弹出toast时,会出现t toast 跳动的现象;关于 position: fixed首先来看,MDN 中对 position: fixed 的说明:

解决微信H5页面软键盘弹起后页面下方留白的问题(iOS端)

微信H5项目,ios端出现了软键盘输完隐藏后页面不会回弹,下方会有一大块留白 最近微信和ios都有版本升级,不知道是哪边升级造成的,但是经过测试,软键盘收起后,再滚动一下页面,下面的留白就会消失

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!