原生JS实现城市选择(输入提示)组控件

先看效果图:

功能需求:

  • 国内城市、国际城市切换
  • 首字母索引分类
  • 输入变化提示

HTML代码

<div class="m-list">
       <div class="g-sch">
        <ul class="f-cb z-blankhide">
         <li class="first">
          <p class="u-unit">
           <label class="u-lab"><b>出发</b></label>
           <span class="u-fromE"><span class="u-ipt s-w168"><input data-type="depart" oninput="inputChange(event)"
              onfocus="openCityPopup(event)" type="text" class="s-w168" id="departCity" /></span></span>
          </p>
          <span class="u-change"><i class="s-png"></i></span>
         </li>
         <li>
          <p class="u-unit">
           <label class="u-lab"><b>到达</b></label>
           <span class="u-fromE"><span class="u-ipt"><input data-type="arrive" oninput="inputChange(event)"
              onfocus="openCityPopup(event)" type="text" class="s-w168" id="arriveCity" /></span></span>
          </p>
         </li>
         <li>
          <p class="u-unit">
           <label class="u-lab"><b>出发日期</b></label>
           <span class="u-fromE"><span class="u-ipt"><input type="date" class="s-w168" /></span>
          </p>
         </li>
         <li>
          <p class="u-unit">
           <label class="u-lab"><i class="u-checkbox s-png"></i><b class="s-fc-999">返回日期</b></label>
           <span class="u-fromE"><span class="u-ipt"><input type="date" class="s-w168" /></span>
          </p>
         </li>
         <li class="last">
          <a href="details.html" class="u-a1">搜索</a>
          <a href="javascript:;" class="u-a2"><span>搜索更多条件</span><i class="s-png"></i></a>
         </li>
        </ul>
        <ul class="f-cb z-divShow" style="display:none">
         <li>
          <p class="u-unit f-fl">
           <label class="u-lab"><b>乘客类型</b></label>
           <span class="u-fromE">
            <span class="u-select s-w178 z-blankhide">
             <span class="u-select-tt"><span>成人</span><i class="s-png"></i></span>
             <span class="u-select-ct" style="display:none"><a href="">成人</a><br /><a href="">儿童(2-12岁)</a></span>
            </span>
           </span>
          </p>
         </li>
         <li>
          <p class="u-unit f-fl">
           <label class="u-lab"><b>乘客数量</b></label>
           <span class="u-fromE">
            <span class="u-select s-w178 z-blankhide">
             <span class="u-select-tt"><span>1</span><i class="s-png"></i></span>
             <span class="u-select-ct" style="display:none"><a href="">1</a><a href="">2</a><br /><a
               href="">3</a><br /><a href="">4</a></span>
            </span>
           </span>
          </p>
         </li>
         <li>
          <p class="u-unit f-fl">
           <label class="u-lab"><b>舱位等级</b></label>
           <span class="u-fromE">
            <span class="u-select s-w178 z-blankhide">
             <span class="u-select-tt"><span>经济舱</span><i class="s-png"></i></span>
             <span class="u-select-ct" style="display:none"><a href="">豪华经济舱</a><a href="">头等舱</a><br /><a
               href="">商务舱</a><br /><a href="">混合舱</a></span>
            </span>
           </span>
          </p>
         </li>
         <li>
          <p class="u-unit">
           <label class="u-lab"><b>航空公司</b></label>
           <span class="u-fromE"><span class="u-ipt z-blankhide"><input type=""
              class="s-w168" /><b>中文或代码</b></span></span>
          </p>
         </li>
        </ul>
        <p class="u-tishi">如果是多人出游,建议您搜索时选择实际的乘客数量,以便获得更优惠的价格。</p>
       </div>
      </div>

 <dialog id="cityPopup" class="cityPopup">
  <div class="switchBox">
   <ul class="switch">
    <li class="menu" onclick="clickSwitch(event,0)">国内</li>
    <li class="menu" onclick="clickSwitch(event,1)">国际</li>
   </ul>
  </div>
  <div class="citySelectBox">
   <p class="title">支持中文/拼音/简拼/三字码输入</p>
   <ul id="indexList" class="indexList">
    <li id="index1" class="index" data-citySpell="热门" onclick="clickTab(event,0)">热门</li>
    <li id="index2" class="index" data-citySpell="ABCD" onclick=" clickTab(event,1)">ABCD</li>
    <li id="index3" class="index" data-citySpell="EFGH" onclick="clickTab(event,2)">EFGH</li>
    <li id="index4" class="index" data-citySpell="JKLM" onclick="clickTab(event,3)">JKLM</li>
    <li id="index5" class="index" data-citySpell="NPQRS" onclick="clickTab(event,4)">NPQRS
    </li>
    <li id="index6" class="index" data-citySpell="TWX" onclick="clickTab(event,5)">TWX
    </li>
    <li id="index7" class="index" data-citySpell="YZ" onclick="clickTab(event,6)">YZ</li>
   </ul>
   <ul id="interList" class="indexList">
    <li id="index1" class="index" data-citySpell="热门" onclick="clickTab(event,7)">热门</li>
    <li id="index2" class="index" data-citySpell="亚洲" onclick=" clickTab(event,8)">亚洲</li>
    <li id="index2" class="index" data-citySpell="欧洲" onclick=" clickTab(event,9)">欧洲</li>
    <li id="index2" class="index" data-citySpell="美洲" onclick=" clickTab(event,10)">美洲</li>
    <li id="index2" class="index" data-citySpell="非洲" onclick=" clickTab(event,11)">非洲</li>
    <li id="index2" class="index" data-citySpell="大洋洲" onclick=" clickTab(event,12)">大洋洲</li>
   </ul>
   <div class="city-box" id="city-box">
   </div>
  </div>
 </dialog>
 <div id="regListPopup" class="regListPopup">

 </div>

功能实现

  • 输入框输入时,触发自动搜索并展示,因为是本地搜索,所以需要本地数据,代码中所用数据格式为[''beijing|北京|bj|PEK'',"......"]
    // 手动输入变化时自动匹配
    function inputChange() {
        const cityPopup = document.getElementById("cityPopup");
        const regListPopup = document.querySelector(".regListPopup")
        const regListStyle = document.getElementsByClassName("regListPopup")[0]
        const regDiv = document.createElement('div')
        let inputVal
        this.regCityList = []
        if (this.inputType == "depart") {
            inputVal = document.getElementById("departCity").value
            regListStyle.style.top = "650px"
            regListStyle.style.left = "420px"
        } else {
            inputVal = document.getElementById("arriveCity").value
            regListStyle.style.top = "650px"
            regListStyle.style.left = "650px"
        }
        regListStyle.style.display = "block"
        cityPopup.close()
        console.log(inputVal);
        if (!inputVal) { //输入框内容为空
            regListStyle.style.display = "none"
        } else {
            for (let i = 0; i < searchArray.length; i++) {  //匹配输入框内容
                if (searchArray[i].indexOf(inputVal) != -1) {
                    this.regCityList.push(searchArray[i])
                    console.log(this.regCityList);
                }
            }
        }
        regListPopup.innerHTML = '';
        regDiv.innerHTML = ''
        regDiv.className = "reg-list"
        regDiv.innerHTML = `<ul class="reg-Ul">${regCityList.map(city => `<li class="reg-cityName" onclick="regCityClick(event)" data-city="${city}">${city.split('|')[1]} ${city.split('|')[2]}</li>`).join('')}</ul>`
        regListPopup.appendChild(regDiv)
    };
  •  点击输入框时,打开城市列表弹窗
    // 打开选择城市弹窗
    function openCityPopup(e) {
        // console.log(e);
        document.getElementById("cityPopup").show()
        if (e.target.dataset.type == "depart") {
            document.getElementById("cityPopup").style.top = "650px"
            document.getElementById("cityPopup").style.left = "-620px"
            this.inputType = "depart"
        } else {
            document.getElementById("cityPopup").style.top = "650px"
            document.getElementById("cityPopup").style.left = "-160px"
            this.inputType = "arrive"
        }
    };
    // 关闭弹窗
    function closeCityPopup(event) {
        const cityPopup = document.getElementById("cityPopup");
        const departCityInput = document.getElementById("departCity");
        const arriveCityInput = document.getElementById("arriveCity");
        // 检查点击是否在弹窗、出发城市输入框或到达城市输入框之外
        if (!cityPopup.contains(event.target) &&
            event.target !== departCityInput &&
            event.target !== arriveCityInput) {
            cityPopup.close();
        }
    };
  • 获取城市分组,首字母分组,地区分组
    // 获取城市分组
    function getListGroup(cityspell) {
        if (cityspell == "热门") { //热门分组
            const allTitle = document.getElementsByClassName("index");
            allTitle[0].style.color = "#499BFC";
            allTitle[0].style.borderBottom = "#499BFC solid 2px";
            allTitle[7].style.color = "#499BFC";
            allTitle[7].style.borderBottom = "#499BFC solid 2px";
            const cityBox = document.querySelector('.city-box');
            cityBox.innerHTML = '';
            const filteredDiv = document.createElement('div');
            filteredDiv.className = 'filtered-cities';
            if (isInter) {
                filteredDiv.innerHTML = `<ul class="filteredBox">${hotCityList.map(city => `<li class="cityName" data-city="${city}" onclick="cityNameClick(event)">${city.split('|')[1]}</li>`).join('')}</ul>`;
            } else {
                filteredDiv.innerHTML = `<ul class="filteredBox">${hotInterList.map(city => `<li class="cityName" data-city="${city}" onclick="cityNameClick(event)">${city.split('|')[1]}</li>`).join('')}</ul>`;
            }
            cityBox.appendChild(filteredDiv);
        } else {
            // 筛选符合条件的城市列表
            let citySpellArray = []
            let interSpellArray = ""
            let filteredCities = [];
            if (this.isInter) {
                citySpellArray = [...cityspell]
                console.log(citySpellArray);
            } else {
                interSpellArray = cityspell
                console.log(interSpellArray);
            }
            const cityBox = document.querySelector('.city-box');
            cityBox.innerHTML = '';
            if (isInter) {
                for (let i = 0; i < citySpellArray.length; i++) {
                    console.log(i);
                    filteredCities = allUserList_Array.filter(city => city.split('|')[0].charAt(0).toUpperCase() == citySpellArray[i])
                    console.log(filteredCities);
                    const spellDiv = document.createElement('div');
                    spellDiv.className = "spell-list";
                    spellDiv.innerHTML = `<p style="margin-bottom:0;">${citySpellArray[i]}</p>`;
                    cityBox.appendChild(spellDiv);
                    let filteredDiv = document.createElement('div');
                    filteredDiv.className = 'filtered-cities';
                    filteredDiv.innerHTML = `<ul class="filteredBox">${filteredCities.map(city => `<li class="cityName" data-city="${city}" onclick="cityNameClick(event)">${city.split('|')[1]}</li>`).join('')}</ul>`;
                    cityBox.appendChild(filteredDiv);
                }
            } else {
                filteredCities = nationalList.filter(city => city.split('|')[4] == interSpellArray)
                let spellDiv = document.createElement('div');
                spellDiv.className = "spell-list";
                spellDiv.innerHTML = `<p style="margin-bottom:0;">${interSpellArray}</p>`;
                cityBox.appendChild(spellDiv);
                let filteredDiv = document.createElement('div');
                filteredDiv.className = 'filtered-cities';
                filteredDiv.innerHTML = `<ul class="filteredBox">${filteredCities.map(city => `<li class="cityName" data-city="${city}" onclick="cityNameClick(event)">${city.split('|')[1]}</li>`).join('')}</ul>`;
                cityBox.appendChild(filteredDiv);
            }

        }
    };
  • 标签切换事件,国际国内切换,首字母切换,地区切换
   // 点击切换国内/国际
    function clickSwitch(event, seq) {
        // console.log(evnet);
        const allSwitch = document.getElementsByClassName("menu");
        console.log(allSwitch);
        for (let i = 0; i < allSwitch.length; i++) {
            if (i == seq) {
                allSwitch[i].style.color = "#499BFC"
                allSwitch[i].style.backgroundColor = "#fff"
                allSwitch[i].style.borderBottom = "#499BFC solid 2px"
            } else {
                allSwitch[i].style.color = "#333"
                allSwitch[i].style.backgroundColor = "#f3f5f7"
                allSwitch[i].style.borderBottom = "none"
            }
        }
        if (allSwitch[seq].innerText == '国内') {
            this.isInter = true
            document.getElementById("indexList").style.display = "flex"
            document.getElementById("interList").style.display = "none"
            this.getListGroup("热门")
        } else {
            this.isInter = false
            document.getElementById("indexList").style.display = "none"
            document.getElementById("interList").style.display = "flex"
            this.getListGroup("热门")
        }
    };

   // 点击标签事件
    function clickTab(event, seq) {
        const allTitle = document.getElementsByClassName("index");
        // 更改选中后的样式
        for (let i = 0; i < allTitle.length; i++) {
            if (i == seq) {
                allTitle[i].style.color = "#499BFC"
                allTitle[i].style.borderBottom = "#499BFC solid 2px"
            } else {
                allTitle[i].style.color = "#333"
                allTitle[i].style.borderBottom = "none"
            }
        }
        this.getListGroup(event.target.dataset.cityspell)
    };
  • 城市名点击事件,搜索列表点击事件、弹出框列表点击事件
    // 城市名称点击事件
    function cityNameClick(event) {
        console.log(this.inputType);
        const cityPopup = document.getElementById("cityPopup");
        if (this.inputType == "depart") {
            document.getElementById("departCity").value = event.target.dataset.city.split('|')[1]
            cityPopup.close()
        } else {
            document.getElementById("arriveCity").value = event.target.dataset.city.split('|')[1]
            cityPopup.close()
        }
    };
    // 城市名称点击事件
    function regCityClick(event) {
        const cityPopup = document.getElementById("cityPopup");
        if (this.inputType == "depart") {
            document.getElementById("departCity").value = event.target.dataset.city.split('|')[1]
            const regListStyle = document.getElementsByClassName("regListPopup")[0]
            regListStyle.style.display = "none"
        } else {
            document.getElementById("arriveCity").value = event.target.dataset.city.split('|')[1]
            const regListStyle = document.getElementsByClassName("regListPopup")[0]
            regListStyle.style.display = "none"
        }
    }
  • 其他
 // 在文档加载完成后添加事件监听器,当点击弹出框外区域时,关闭弹出框
    document.addEventListener("DOMContentLoaded", function () {
        document.addEventListener("click", closeCityPopup);
    });

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值