仿京东收货地址录入

京东收货地址需要通过浮动列表选择省、市、县、乡来设置,本文试用原生js实现,效果如图;

 

省、市、县、乡代码和名称列表在pcas-code.js文件,可以从网上下载,最新信息请看民政部网站;pcas-code.js定义一个json数组pcas,如图显示为河北省秦皇岛市北戴河区海滨镇;

 

代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="js/pcas-code.js"></script>
        <style type="text/css">
            *,
            :after,
            :before {
                padding: 0px;
                margin: 0px;
            }
            
            body {
                padding-left: 100px;
            }
            
            .area-header-tips {
                color: #999;
                height: 25px;
                line-height: 25px;
                font-size: 12px;
                padding-left: 10px;
                float: left;
                margin-right: 7px;
            }
            
            .area-entrance {
                width: 527px;
                font-size: 12px;
                line-height: 1.6;
            }
            
            .area-header {
                float: left;
                position: relative;
                height: 23px;
                line-height: 23px;
                padding: 0 24px 0 4px;
                border: 1px solid #CECBCE;
                top: 0;
                background-color: #fff;
            }
            
            .area-header-hover {
                z-index: 1;
                height: 25px;
                border-bottom: 0;
            }
            
            .area-header-input {
                font-size: 12px;
                color: #666;
                overflow: hidden;
            }
            
            .area-header-icon {
                background: url(img/iconset.png) no-repeat 3px 5px;
                width: 17px;
                height: 17px;
                position: absolute;
                top: 3px;
                right: 4px;
            }
            
            .area-box {
                width: 460px;
                display: none;
                float: left;
                border: 1px solid #CECBCE;
                color: #005AA0;
                padding: 12px 12px 15px;
                position: absolute;
                top: 25px;
                left: 60px;
                box-shadow: 0 0 5px #ddd;
            }
            
            .area-box-hover {
                display: block;
            }
            
            .area-box-title ul {
                display: flex;
                list-style: none;
                padding: 0px;
                margin: 0px;
                width: 423px;
                height: 25px;
                border-bottom: 2px solid #e4393c;
            }
            
            .area-box-title ul li {
                display: none;
                text-align: center;
                background-color: #FFF;
                border-bottom: 0;
                margin-right: 4px;
                overflow: hidden;
                float: left;
                position: relative;
            }
            em{
                font-style: normal;
            }
            .area-box-title ul li i {
                background: url(img/iconset.png) no-repeat 0 5px;
                position: absolute;
                right: 6px;
                top: 5px;
                display: block;
                width: 13px;
                height: 16px;
                overflow: hidden;
                opacity: .5;
            }
            
            .area-box-title .area-box-title-visible {
                display: block;
                height: 23px;
                line-height: 23px;
                border: 1px solid #ddd;
                border-bottom: 0;
                padding: 0 25px 1px 6px;
            }
            
            .area-box-title .area-box-title-current {
                display: block;
                height: 25px;
                line-height: 25px;
                border: 2px solid #e4393c;
                border-bottom: 0;
                padding: 0 25px 0 6px;
            }
            
            .area-box-title ul li:hover {
                cursor: pointer;
            }
            
            .area-box-content-panel {
                display: none;
            }
            
            .area-box-content-current {
                display: block;
            }
            
            .area-box-content-panel ul {
                list-style: none;
                padding-top: 10px;
                overflow: auto;
                margin-bottom: -5px;
            }
            
            .area-box-content-list li {
                padding: 0 16px 1px 0;
                float: left;
                width: 80px;
                line-height: 150%;
                display: list-item;
            }
            
            .area-box-content-list .long-area {
                width: 176px;
            }
            
            .area-box-content-list li:hover {
                color: #4a8cff;
            }
            
            .area-box-content-list li a {
                display: block;
                padding: 2px 4px 2px 0;
                color: #005aa0;
                text-decoration: none;
            }
            
            .area-box-content-list li.area-current a {
                color: #e4393c;
            }
            
            .area {
                position: absolute;
                left: 300px;
                top: 100px;
            }
        </style>
    </head>

    <body>
        <div class="area">
            <div class="area-header-tips"><label>配  送  至</label></div>
            <div class="area-entrance" id="area-entrance">
                <div class="area-header">
                    <span class="area-header-input">
                        <span class="placeholder"></span>
                    </span>
                    <span class="area-header-icon"></span>
                </div>
                <div class="area-box">
                    <div class="area-box-title">
                        <ul>
                            <li><em></em><i></i></li>
                            <li><em></em><i></i></li>
                            <li><em></em><i></i></li>
                            <li><em>街道</em><i></i></li>
                        </ul>
                    </div>
                    <div class="area-box-content">
                        <div class="area-box-content-panel">
                            <ul class="area-box-content-list">
                            </ul>
                        </div>
                        <div class="area-box-content-panel">
                            <ul class="area-box-content-list">
                            </ul>
                        </div>
                        <div class="area-box-content-panel">
                            <ul class="area-box-content-list">
                            </ul>
                        </div>
                        <div class="area-box-content-panel">
                            <ul class="area-box-content-list">

                            </ul>
                        </div>
                    </div>
                </div>

            </div>
        </div>
    </body>

    <script type="text/javascript">
        /* 添加事件监听函数
         * obj 要添加监听的对象或元素 
         * eventName 事件名 
         * fun 监听函数的名称 
         * param 给监听函数传的参数, 这里就传了一个参数 
         */
        function addEventHandler(obj, eventName, fun, param) {
            var fn = fun;
            if (param != undefined) {
                fn = function(e) {
                    fun.call(this, param); //继承监听函数,并传入参数以初始化;
                }
            }
            if (obj.addEventListener) {
                // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
                obj.addEventListener(eventName, fn, false);
            } else if (obj.attachEvent) {
                // IE8.0及其以下版本
                obj.attachEvent('on' + eventName, fn);
            } else {
                // 早期浏览器
                obj["on" + eventName] = fn;
            }
        }
        /* 
         * 采用事件监听给对象绑定方法后,可以解除相应的绑定 
         *  oTarget:监听对象 
         *  sEventType:监听事件类型,如click,mouseover 
         *  fnHandler:监听函数 
         */
        function removeEventHandler(oTarget, sEventType, fnHandler) {
            if (oTarget.removeEventListener) {
                // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
                oTarget.removeEventListener(sEventType, fnHandler, false);
            } else if (oTarget.detachEvent) {
                // IE 8 及更早IE版本
                oTarget.detachEvent("on" + sEventType, fnHandler);
            } else {
                // 早期浏览器
                delete oTarget["on" + sEventType];
            }
        }
        /*
         * 停止冒泡行为
         */
        function stopBubble(e) {
            //如果提供了事件对象,则这是一个非IE浏览器 
            if (e && e.stopPropagation)
            //因此它支持W3C的stopPropagation()方法 
                e.stopPropagation();
            else
            //否则,我们需要使用IE的方式来取消事件冒泡 
                window.event.cancelBubble = true;
        }
        //触发点击事件
        function triggerclick(obj) {
            //IE
            if (document.all) {
                obj.click();
            }
            // 其它浏览器
            else {
                var e = document.createEvent("MouseEvents");
                e.initEvent("click", true, true);  //这里的click可以换成你想触发的行为
                obj.dispatchEvent(e);    ////这里的clickME可以换成你想触发行为的DOM结点
            }
        }
        //判断是否IE
        function _isIE() {
            var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
            var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
            var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
            var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
            if (isIE)
                return true;
            else if (isEdge) //edge
                return true;
            else if (isIE11)
                return true;
            else return false;
        }
        
        var area_entrance = document.getElementById('area-entrance');
        var area_header = area_entrance.getElementsByClassName('area-header')[0];
        var area_header_tips = document.getElementsByClassName('area-header-tips')[0];
        var area_header_input = area_entrance.getElementsByClassName('area-header-input')[0];
        var area_box = area_entrance.getElementsByClassName('area-box')[0];
        var area_box_title = area_entrance.getElementsByClassName('area-box-title')[0];
        var area_box_content = area_entrance.getElementsByClassName('area-box-content')[0];
        var area_box_content_panel = area_box_content.getElementsByClassName('area-box-content-panel');
        var area_box_content_list = area_entrance.getElementsByClassName('area-box-content-list');
        var area_current = area_entrance.getElementsByClassName('area-current');
        //json格式默认收货地址
        var area_address = {
            code: "13",
            name: "河北省",
            children: {
                code: "1303",
                name: "秦皇岛市",
                children: {
                    code: "130304",
                    name: "北戴河区",
                    children: {
                        code: "130304100",
                        name: "海滨镇",
                    }
                }
            }
        };
        //默认收货地址文本
        var default_address = '';
        //默认收货地址代码
        var default_province = area_address ? area_address.code : '',
            default_city = area_address && area_address.children ? area_address.children.code : '',
            default_county = area_address && area_address.children && area_address.children.children ? area_address.children.children.code : '',
            default_street = area_address && area_address.children && area_address.children.children && area_address.children.children.children ? area_address.children.children.children.code : '';
        //中间变量
        var temp_address = area_address;
        while (temp_address) {
            default_address += temp_address.name ? temp_address.name : '';
            temp_address = temp_address.children;
        }
        //显示默认地址
        area_header_input.children[0].innerText = default_address;
        //处理标题切换
        function area_box_title_handle(e) {
            e = e || window.event;  //IE window.event
            var t = e.target || e.srcElement; //目标对象
            //标题切换
            for (var i = 0; i < area_box_title.children[0].children.length; i++) {
                if (area_box_title.children[0].children[i] == this) {
                    //显示当前列表
                    area_box_content_panel[i].classList.add('area-box-content-current');
                    //修改当前标题边框为红色
                    area_box_title.children[0].children[i].classList.remove('area-box-title-visible');
                    area_box_title.children[0].children[i].classList.add('area-box-title-current');
                } else {
                    //隐藏其余列表显示
                    area_box_content_panel[i].classList.remove('area-box-content-current');
                    //修改当前标题边框为灰色
                    area_box_title.children[0].children[i].classList.remove('area-box-title-current');
                    area_box_title.children[0].children[i].classList.add('area-box-title-visible');
                }
            }
        }
        //省级标题背景变白色
        area_box_title.children[0].children[0].classList.add('area-box-title-current');
        //省级标题绑定点击事件
        addEventHandler(area_box_title.children[0].children[0], 'click', area_box_title_handle);
        //显示省级列表
        area_box_content_panel[0].classList.add('area-box-content-current');
        //获取省级节点数组
        var province = getSubLevel('0');
        //添加节点到展示列表
        for (var i = 0; i < province.length; i++) {
            //文字太长加样式
            if (province[i].name.length >= 6) {
                area_box_content_list[0].innerHTML += '<li class="long-area"><a code=' + province[i].code + ' href="javascript:void(0)">' + province[i].name + '</a></li>';
            } else {
                area_box_content_list[0].innerHTML += '<li><a code=' + province[i].code + ' href="javascript:void(0)">' + province[i].name + '</a></li>';
            }
        }
        //每个省级节点绑定点击事件,使用事件代理
        addEventHandler(area_box_content_list[0], 'click', area_box_content_list_handle, 0);
        //为选中省级节点触发点击事件
        if (default_province) {
            for (var i = 0; i < area_box_content_list[0].children.length; i++) {
                if (area_box_content_list[0].children[i].children[0].getAttribute('code') == default_province) {
                    triggerclick(area_box_content_list[0].children[i].children[0]);
                }
            }
        }
        //为选中市级节点触发点击事件
        if (default_city) {
            for (var i = 0; i < area_box_content_list[1].children.length; i++) {
                if (area_box_content_list[1].children[i].children[0].getAttribute('code') == default_city) {
                    triggerclick(area_box_content_list[1].children[i].children[0]);
                }
            }
        }
        //为选中区级节点触发点击事件
        if (default_county) {
            for (var i = 0; i < area_box_content_list[2].children.length; i++) {
                if (area_box_content_list[2].children[i].children[0].getAttribute('code') == default_county) {
                    triggerclick(area_box_content_list[2].children[i].children[0]);
                }
            }
        }
        //为选中街道节点触发点击事件
        if (default_street) {
            for (var i = 0; i < area_box_content_list[3].children.length; i++) {
                if (area_box_content_list[3].children[i].children[0].getAttribute('code') == default_street) {
                    triggerclick(area_box_content_list[3].children[i].children[0]);
                }
            }
        }
        //鼠标经过地址栏弹出选择列表
        function area_box_hover_handle(e) {
            e = e || window.event;  //IE window.event
            var t = e.target || e.srcElement; //目标对象
            //地址栏宽度+左右内边距和边框-选择列表总宽度+定位左坐标
            var offsetInt = Number(window.getComputedStyle(area_header).width.replace('px', '')) + 30 - 486 + 60;
            var offsetStr = offsetInt + 'px';
            //隐藏输入框下边框
            area_header.classList.add('area-header-hover');
            //显示选择列表
            area_box.classList.add('area-box-hover');
            //根据浏览器可视区域调整
            if (!(document.body.clientWidth >= 933)) {
                area_box.style.left = offsetStr;
            } else {
                area_box.style.left = '60px';
            }
            //取消冒泡
            stopBubble(e);
            //移入后绑定移出事件
            addEventHandler(area_header, 'mouseout', area_box_out_handle);
            addEventHandler(area_box, 'mouseout', area_box_out_handle);
        }
        //地址栏绑定移入事件
        addEventHandler(area_header, 'mouseover', area_box_hover_handle);
        //展示列表绑定移入事件
        addEventHandler(area_box, 'mouseover', area_box_hover_handle);
        //关闭选择列表
        function area_box_out_handle() {
            //去除类别标识
            //显示输入框下边框
            area_header.classList.remove('area-header-hover');
            //隐藏选择列表
            area_box.classList.remove('area-box-hover');
        }
        //本级节点绑定点击事件
        function area_box_content_list_handle(index, e) {
            e = e || window.event;  //IE window.event
            var t = e.target || e.srcElement; //目标对象
            
            //点击上级节点不处理,2020-01-03
            if (t.tagName != 'A') return;
            
            var tli = t.parentElement;
            var arrSubLevel = getSubLevel(t.getAttribute('code'));
            var fillContent = '';
            //取消移出事件
            removeEventHandler(area_header, 'mouseout', area_box_out_handle);
            removeEventHandler(area_box, 'mouseout', area_box_out_handle);
            //当前选择节点变红色
            for (var i = 0; i < area_box_content_list[index].children.length; i++) {
                if (area_box_content_list[index].children[i] == tli) {
                    tli.classList.add('area-current');
                } else {
                    area_box_content_list[index].children[i].classList.remove('area-current');
                }
            }
            //本级标题改为所选地址
            if (_isIE()) {
                //IE浏览器不支持display:flex属性,支持float,截取五个汉字,以免超长无法显示
                area_box_title.children[0].children[index].innerHTML ='<em>'+ t.innerText.substring(0, 5)+'</em><i></i>';
            } else {
                //其余浏览器支持display:flex属性,自动截短
                area_box_title.children[0].children[index].innerHTML ='<em>'+t.innerText+'</em><i></i>';
            }
            //点击街道退出
            if (index == 3) {
                //选中地址填充到输入框
                for (var i = 0; i < area_current.length; i++) {
                    fillContent += area_current[i].children[0].innerText;
                }
                area_header_input.innerHTML = fillContent;
                //关闭弹窗
                area_box_out_handle();
                //取消冒泡
                stopBubble(e);
                return;
            }
            //本级标题变色
            area_box_title.children[0].children[index].classList.remove('area-box-title-current');
            area_box_title.children[0].children[index].classList.add('area-box-title-visible');
            //次级标题改为'请选择'
            area_box_title.children[0].children[index + 1].innerHTML = '<em>'+'请选择'+'</em><i></i>';
            //次级标题显示
            //            area_box_title.children[0].children[index + 1].classList.add('area-box-title-visible');
            //次级标题变色
            area_box_title.children[0].children[index + 1].classList.add('area-box-title-current');
            //次级标题绑定点击事件
            if (area_box_title.children[0].children.length > index + 1) {
                addEventHandler(area_box_title.children[0].children[index + 1], 'click', area_box_title_handle);
            }
            //取消后续标题绑定点击事件
            for (var i = area_box_title.children[0].children.length - 1; i > index + 1; i--) {
                removeEventHandler(area_box_title.children[0].children[i], 'click', area_box_title_handle);
                //隐藏后续标题
                area_box_title.children[0].children[i].classList.remove('area-box-title-visible');
            }
            //切换显示选择列表
            area_box_content_panel[index].classList.remove('area-box-content-current');
            area_box_content_panel[index + 1].classList.add('area-box-content-current');
            
            //填充次级可选节点,首先清空
            area_box_content_panel[index + 1].children[0].innerHTML = '';
            for (var i = 0; i < arrSubLevel.length; i++) {
                //文字太长加样式
                if (arrSubLevel[i].name.length >= 6) {
                    area_box_content_panel[index + 1].children[0].innerHTML += '<li class="long-area"><a code=' + arrSubLevel[i].code + ' href="javascript:void(0)">' + arrSubLevel[i].name + '</a></li>';
                } else {
                    area_box_content_panel[index + 1].children[0].innerHTML += '<li><a code=' + arrSubLevel[i].code + ' href="javascript:void(0)">' + arrSubLevel[i].name + '</a></li>';
                }
            }
            
            //为上级节点绑定次级可选节点点击事件,2020-01-03
            addEventHandler(area_box_content_panel[index + 1], 'click', area_box_content_list_handle, index + 1);
            
        }
        //根据所选地址code查找子级节点,返回数组,找不到返回undefined
        function getSubLevel(code) {
            var cities, areas, streets, rValue;
            if (!code) {
                return;
            }
            //点击地址栏,返回所有节点
            if (code == '0') {
                rValue = pcas;
                return rValue;
            }
            
            //点击省级节点,返回市级列表数组
            for (var i = 0; i < pcas.length; i++) {
                if (pcas[i].code == code) {
                    //刚好是省级节点
                    rValue = pcas[i].children;
                    return rValue;
                } else if (pcas[i].code == code.substring(0, 2)) {
                    //前两位是省级节点
                    cities = pcas[i].children;
                    break;
                }
            }
            //点击市级节点,返回区级列表数组
            if (cities) {
                for (var i = 0; i < cities.length; i++) {
                    if (cities[i].code == code) {
                        rValue = cities[i].children;
                        return rValue;
                    } else if (cities[i].code == code.substring(0, 4)) {
                        areas = cities[i].children;
                        break;
                    }
                }
            }
            //点击区县级节点,返回街道列表数组
            if (areas) {
                for (var i = 0; i < areas.length; i++) {
                    if (areas[i].code == code) {
                        rValue = areas[i].children;
                        return rValue;
                    } else if (areas[i].code == code.substring(0, 6)) {
                        streets = areas[i].children;
                        break;
                    }
                }
            }
            return rValue;
        }
    </script>
</html>
posted @ 2019-11-20 19:50  老余的水壶  阅读(1647)  评论(0)    收藏  举报