仿淘宝收货地址录入

淘宝收货地址需要通过下拉列表选择省、市、县、乡来设置,本文试用原生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 {
                box-sizing: border-box;
                color: #333;
                padding: 0px;
                margin: 0px;
            }
            
            .area-entrance {
                width: 427px;
                font-size: 12px;
                line-height: 1.6;
            }
            .area-header{
                font-size: 0px;
            }
            .area-header-tips {
                display: inline-block;
                padding-right: 12px;
                color: #333;
                width: 78px;
                line-height: 30px;
                vertical-align:top;
                font-size: 12px;
            }
            
            .area-header-tips:before {
                margin-right: 4px;
                content: "*";
                color: #ff3000;
            }
            
            .area-header-click {
                display: inline-block;
                position: relative;
                width: 336px;
                /*min-height: 28px;*/
                /*vertical-align: middle;*/
                line-height: 28px;
                padding: 0px 8px;
                border: 1px solid #CCCCCC;
                border-radius: 3px;
            }
            
            .area-header-click:hover {
                cursor: pointer;
            }
            
            .placeholder {
                color: #999;
            }
            .area-header-click-input{
                display: inline-block;
                width: 318px;
                /*height: 28px;*/
                line-height: 28px;
                vertical-align: top;
                font-size: 12px;
                /*overflow: visible;*/
                min-height: 28px;
            }
            .area-input-name{
                display: inline-block;
                margin: -2px 5px;
                overflow: hidden;
                vertical-align: top;
            }
            
            .area-input-symbol{
                /*vertical-align: top;*/
            }
            .area-header-click-icon {
                background: url(img/down.png) no-repeat center right;
                display: inline-block;
                width: 11px;
                height: 6px;
                position: absolute;
                top: 10px;
                right: 8px;
            }
            
            .area-box {
                display: none;
                border: 1px solid #CCCCCC;
            }
            .area-box-title ul {
                display: flex;
                list-style: none;
                padding: 0px;
                margin: 0px;
                height: 30px;
                border-bottom: 1px solid #ccc;
            }
            
            .area-box-title ul li {
                width: 25%;
                /*flex: 1;*/
                float: left;
                height: 29px;
                line-height: 29px;
                text-align: center;
                background-color: #F0F0F0;
            }
            .area-box-title .area-box-title-current{
                background-color: #FFF;
            }
            
            .area-box-title ul li:hover {
                cursor: pointer;
            }
            .area-box-content-panel {
                display: none;
            }
            .area-box-content-visible {
                display: block;
            }
            .area-box-content-panel ul {
                height: 320px;
                list-style: none;
                padding: 0px;
                overflow: auto;
                margin: 5px 10px;
            }
            
            .area-box-content-list li {
                padding: 10px 5px;
            }
            
            .area-box-content-list li:hover {
                color: #4a8cff;
            }
            
            .area-current {
                color: #4a8cff;
                font-weight: 700;
            }
            
            .area{
                position: absolute;
                left: 300px;
                top: 100px;
            }
        </style>
    </head>

    <body>
        <div class="area">
        <div class="area-entrance" id="area-entrance">
            <div class="area-header">
                <span class="area-header-tips"><label>地址信息:</label></span>
                <div class="area-header-click"><span class="area-header-click-input">
                    <span class="placeholder">请选择省/市/区/街道</span></span>
                    <span class="area-header-click-icon"></span>
                </div>
            </div>
            <div class="area-box">
                <div class="area-box-title" >
                    <ul>
                        <li></li>
                        <li></li>
                        <li></li>
                        <li>街道</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.attachEvent) {
                obj.attachEvent('on' + eventName, fn);
            } else if (obj.addEventListener) {
                obj.addEventListener(eventName, fn, false);
            } else {
                obj["on" + eventName] = fn;
            }
        }
        /* 
         *  采用事件监听给对象绑定方法后,可以解除相应的绑定 
         *  oTarget:监听对象 
         *  sEventType:监听事件类型,如click,mouseover 
         *  fnHandler:监听函数 
         */
        function removeEventHandler(oTarget, sEventType, fnHandler) {
            if (oTarget.removeEventListener) {
                //监听IE9,谷歌和火狐  
                oTarget.removeEventListener(sEventType, fnHandler, false);
            } else if (oTarget.detachEvent) {
                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;
        }
        
        var area_entrance = document.getElementById('area-entrance');
        var area_header = area_entrance.getElementsByClassName('area-header')[0];
        var area_header_tips = area_entrance.getElementsByClassName('area-header-tips')[0];
        var area_header_click = area_entrance.getElementsByClassName('area-header-click')[0];
        var area_header_click_input = area_entrance.getElementsByClassName('area-header-click-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');
        var area_box_content_panel = area_entrance.getElementsByClassName('area-box-content-panel');
        var area_box_content_list = area_entrance.getElementsByClassName('area-box-content-list');
        
        //处理标题切换
        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] == t) {
                    //把当前标题背景设置为白色
                    area_box_title.children[0].children[i].classList.add('area-box-title-current');
                    //显示当前列表
                    area_box_content_panel[i].classList.add('area-box-content-visible');
                    
                } else {
                    //把其余标题背景设置为灰色
                    area_box_title.children[0].children[i].classList.remove('area-box-title-current');
                    //隐藏其余列表显示
                    area_box_content_panel[i].classList.remove('area-box-content-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-visible');
        //获取省级节点数组
        var province = getSubLevel('0');
        //添加节点到展示列表
        for (var i = 0; i < province.length; i++) {
            area_box_content_list[0].innerHTML += '<li code=' + province[i].code + '>' + province[i].name + '</li>';
        }
        
        //为父节点绑定省级节点点击事件,2020-01-03
        addEventHandler(area_box_content_list[0], 'click', area_box_content_list_handle, 0);
        
        //切换选择列表
        function area_header_click_toggle(e) {
            e = e || window.event;  //IE window.event
            var t = e.target || e.srcElement; //目标对象
            //切换 选择列表
            if(document.defaultView.getComputedStyle(area_box).display== 'none'){
                area_box.classList.add('area-box-content-visible');
            }else{
                area_box.classList.remove('area-box-content-visible');
            }
            
            //取消冒泡
            stopBubble(e);
        }
        //地址栏绑定点击事件
        addEventHandler(area_header_click, 'click', area_header_click_toggle);
        //弹出选择列表
        function area_header_click_handle(e) {
            e = e || window.event;  //IE window.event
            var t = e.target || e.srcElement; //目标对象
            //显示选择列表
            area_box.classList.add('area-box-content-visible');
            //取消冒泡
            stopBubble(e);
        }
        //展示列表绑定点击事件
        addEventHandler(area_box, 'click', area_header_click_handle);
        //关闭选择列表
        function close_area_box_handle() {
            //隐藏选择列表
            area_box.classList.remove('area-box-content-visible');
        }
        //文档其余部分绑定点击事件
        addEventHandler(document, 'click', close_area_box_handle);
        //本级节点绑定点击事件
        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 != 'LI') return;
            //获取下级行政区划
            var arrSubLevel = getSubLevel(t.getAttribute('code'));
            var fillContent;
            //当前选择节点变蓝色
            for (var i = 0; i < area_box_content_list[index].children.length; i++) {
                if (area_box_content_list[index].children[i] == t) {
                    t.classList.add('area-current');
                } else {
                    area_box_content_list[index].children[i].classList.remove('area-current');
                }
            }
            //清空本级及后续输入地址
            for (var i = area_header_click_input.children.length - 1; i >= index; i--) {
                area_header_click_input.children[i].outerHTML = '';
            }
            //选中地址填充到输入框
            fillContent='<span><span class="area-input-name">' + t.innerText ;
            //街道没有斜线
            if (index == 3){
                fillContent+='</span><span class="area-input-symbol"></span></span>';
            }else{
                fillContent+='</span><span class="area-input-symbol">/</span></span>';
            }
            //暂不选择不进入输入框
            if(t.innerText=='暂不选择'){
                fillContent='';
            }
            area_header_click_input.innerHTML += fillContent;
            //点击街道退出
            if (index == 3){
                close_area_box_handle();
                //取消冒泡
                stopBubble(e);
                return;
            }
            //次级标题绑定点击事件
            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[index + 1].classList.add('area-box-title-current');
            area_box_content_panel[index + 1].classList.add('area-box-content-visible');
            
            //隐藏本级标题
            area_box_title.children[0].children[index].classList.remove('area-box-title-current');
            area_box_content_panel[index].classList.remove('area-box-content-visible');
            
            //填充次级可选节点,首先清空
            area_box_content_panel[index + 1].children[0].innerHTML = '';
            if (index == 2){
                area_box_content_panel[index + 1].children[0].innerHTML += '<li code=' + '0' + '>' + '暂不选择' + '</li>';
            }
            for (var i = 0; i < arrSubLevel.length; i++) {
                area_box_content_panel[index + 1].children[0].innerHTML += '<li code=' + arrSubLevel[i].code + '>' + arrSubLevel[i].name + '</li>';
            }
            
            //为父节点绑定可选节点点击事件,2020-01-03
            addEventHandler(area_box_content_panel[index + 1].children[0], '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;
            }
            var code2 = code.substring(0, 2);
            //点击省级节点,返回市级列表数组
            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 18:40  老余的水壶  阅读(2128)  评论(0)    收藏  举报