jQuery插件实现适用于移动端的地址选择器


Posted in Javascript onFebruary 18, 2016

最近在工作中需要用到地址选择器,像下面这样的,本想在网上找一个,可是没找到,于是自己写了个jquery插件。

jQuery插件实现适用于移动端的地址选择器

直接上代码吧:

var provinces = {
 "A": {
 "安徽":["合肥市","芜湖市","蚌埠市","淮南市","马鞍山市","淮北市","铜陵市","安庆市","黄山市","滁州市","阜阳市","宿州市","巢湖市","六安市","亳州市","池州市","宣城市"]
 },
 "B": {
 "北京": ["北京市"]
 },
 "C": {
 "重庆":["重庆市"]
 },
 "F": {
 "福建":["福州市","厦门市","莆田市","三明市","泉州市","漳州市","南平市","龙岩市","宁德市"]
 },
 "G": {
 "甘肃":["兰州市","嘉峪关市","金昌市","白银市","天水市","武威市","张掖市","平凉市","酒泉市","庆阳市","定西市","陇南市","临夏回族自治州","甘南藏族自治州"],
 "广东":["广州市","深圳市","珠海市","汕头市","韶关市","佛山市","江门市","湛江市","茂名市","肇庆市","惠州市","梅州市","汕尾市","河源市","阳江市","清远市","东莞市","中山市","潮州市","揭阳市","云浮市"],
 "广西":["南宁市","柳州市","桂林市","梧州市","北海市","防城港市","钦州市","贵港市","玉林市","百色市","贺州市","河池市","来宾市","崇左市"],
 "贵州":["贵阳市","六盘水市","遵义市","安顺市","铜仁地区","黔西南布依族苗族自治州","毕节地区","黔东南苗族侗族自治州","黔南布依族苗族自治州"]
 },
 "H": {
 "海南":["海口市","三亚市"],
 "河北":["石家庄市","唐山市","秦皇岛市","邯郸市","邢台市","保定市","张家口市","承德市","沧州市","廊坊市","衡水市"],
 "河南":["郑州市","开封市","洛阳市","平顶山市","安阳市","鹤壁市","新乡市","焦作市","濮阳市","许昌市","漯河市","三门峡市","南阳市","商丘市","信阳市","周口市","驻马店市"],
 "黑龙江":["哈尔滨市","齐齐哈尔市","鸡西市","鹤岗市","双鸭山市","大庆市","伊春市","佳木斯市","七台河市","牡丹江市","黑河市","绥化市","大兴安岭地区"],
 "湖北":["武汉市","黄石市","十堰市","宜昌市","襄樊市","鄂州市","荆门市","孝感市","荆州市","黄冈市","咸宁市","随州市","恩施土家族苗族自治州","神农架"],
 "湖南":["长沙市","株洲市","湘潭市","衡阳市","邵阳市","岳阳市","常德市","张家界市","益阳市","郴州市","永州市","怀化市","娄底市","湘西土家族苗族自治州"]
 },
 "J": {
 "吉林":["长春市","吉林市","四平市","辽源市","通化市","白山市","松原市","白城市","延边朝鲜族自治州"],
 "江苏":["南京市","无锡市","徐州市","常州市","苏州市","南通市","连云港市","淮安市","盐城市","扬州市","镇江市","泰州市","宿迁市"],
 "江西":["南昌市","景德镇市","萍乡市","九江市","新余市","鹰潭市","赣州市","吉安市","宜春市","抚州市","上饶市"]
 },
 "L": {
 "辽宁":["沈阳市","大连市","鞍山市","抚顺市","本溪市","丹东市","锦州市","营口市","阜新市","辽阳市","盘锦市","铁岭市","朝阳市","葫芦岛市"]
 },
 "N": {
 "内蒙古":["呼和浩特市","包头市","乌海市","赤峰市","通辽市","鄂尔多斯市","呼伦贝尔市","巴彦淖尔市","乌兰察布市","兴安盟","锡林郭勒盟","阿拉善盟"],
 "宁夏":["银川市","石嘴山市","吴忠市","固原市","中卫市"]
 },
 "Q": {
 "青海":["西宁市","海东地区","海北藏族自治州","黄南藏族自治州","海南藏族自治州","果洛藏族自治州","玉树藏族自治州","海西蒙古族藏族自治州"]
 },
 "S": {
 "山东":["济南市","青岛市","淄博市","枣庄市","东营市","烟台市","潍坊市","济宁市","泰安市","威海市","日照市","莱芜市","临沂市","德州市","聊城市","滨州市","菏泽市"],
 "山西":["太原市","大同市","阳泉市","长治市","晋城市","朔州市","晋中市","运城市","忻州市","临汾市","吕梁市"],
 "陕西":["西安市","铜川市","宝鸡市","咸阳市","渭南市","延安市","汉中市","榆林市","安康市","商洛市"],
 "上海":["上海市"],
 "四川":["成都市","自贡市","攀枝花市","泸州市","德阳市","绵阳市","广元市","遂宁市","内江市","乐山市","南充市","眉山市","宜宾市","广安市","达州市","雅安市","巴中市","资阳市","阿坝藏族羌族自治州","甘孜藏族自治州","凉山彝族自治州"]
 },
 "T": {
 "天津": ["天津市"]
 },
 "X": {
 "西藏":["拉萨市","昌都地区","山南地区","日喀则地区","那曲地区","阿里地区","林芝地区"],
 "新疆":["乌鲁木齐市","克拉玛依市","吐鲁番地区","哈密地区","昌吉回族自治州","博尔塔拉蒙古自治州","巴音郭楞蒙古自治州","阿克苏地区","克孜勒苏柯尔克孜自治州","喀什地区","和田地区","伊犁哈萨克自治州","塔城地区","阿勒泰地区","石河子市","阿拉尔市","图木舒克市","五家渠市"]
 },
 "Y": {
 "云南":["昆明市","曲靖市","玉溪市","保山市","昭通市","丽江市","思茅市","临沧市","楚雄彝族自治州","红河哈尼族彝族自治州","文山壮族苗族自治州","西双版纳傣族自治州","大理白族自治州","德宏傣族景颇族自治州","怒江傈僳族自治州","迪庆藏族自治州"]
 },
 "Z": {
 "浙江":["杭州市","宁波市","温州市","嘉兴市","湖州市","绍兴市","金华市","衢州市","舟山市","台州市","丽水市"]
 }
};

(function ($, win, doc) {
 var CityPicker = function (el, options) {
 this.el = $(el);
 this.options = options;
 this.provinces = provinces;
 this.pro = null;
 this.city = null;
 this.elType = this.el.is('input');

 this.init();
 };

 var p = CityPicker.prototype;

 p.init = function () {
 this.initEvent();
 this.preventPopKeyboard();

 };

 p.preventPopKeyboard = function () {
 if (this.elType) {
  this.el.prop("readonly", true);
 }
 };

 p.initEvent = function () {
 this.el.on("focus", function (e) {
  var pickerBox = $(".picker-box");
  if (pickerBox[0]) {
  pickerBox.show();
  } else {
  this.create();
  }
 }.bind(this));
 };

 p.create = function () {
 this.createCityPickerBox();
 this.createProList();
 this.proClick();
 this.createNavBar();
 this.navEvent();
 };

 p.createCityPickerBox = function () {
 var proBox = "<div class='picker-box'></div>";
 $("body").append(proBox);
 };

 p.createProList = function () {
 var provinces = this.provinces;
 var proBox;
 var dl = "";
 for (var letterKey in provinces) {
  var val = provinces[letterKey];
  if (provinces.hasOwnProperty(letterKey)) {
  var dt = "<dt id='" + letterKey + "'>" + letterKey + "</dt>";
  var dd = "";
  for (var proKey in val) {
   if (val.hasOwnProperty(proKey)) {
   dd += "<dd data-letter=" + letterKey + ">" + proKey + "</dd>";
   }
  }
  dl += "<dl>" + dt + dd + "</dl>";
  }
 }

 proBox = "<section class='pro-picker'>" + dl + "</section>";

 $(".picker-box").append(proBox);
 };

 p.createCityList = function (letter, pro) {
 var cities = this.provinces[letter][pro];
 var ul, li = "";
 cities.forEach(function (city, i) {
  li += "<li>" + city + "</li>";
 });

 ul = "<ul class='city-picker'>" + li + "</ul>";
 $(".picker-box").find(".city-picker").remove().end().append(ul);

 this.cityClick();
 };

 p.proClick = function () {
 var that = this;
 $(".pro-picker").on("click", function (e) {
  var target = e.target;
  if ($(target).is("dd")) {
  that.pro = $(target).html();
  var letter = $(target).data("letter");
  that.createCityList(letter, that.pro);

  $(this).hide();
  }
 });
 };

 p.cityClick = function () {
 var that = this;
 $(".city-picker").on("click", function (e) {
  var target = e.target;
  if ($(target).is("li")) {
  that.city = $(target).html();
  if (that.elType) {
   that.el.val(that.pro + "-" + that.city);
  } else {
   that.el.html(that.pro + "-" + that.city);
  }

  $(".picker-box").hide();
  $(".pro-picker").show();
  $(this).hide();
  }
 });
 };

 p.createNavBar = function () {
 var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 var arr = str.split("");
 var a = "";
 arr.forEach(function (item, i) {
  a += '<a href="#' + item + '">' + item + '</a>';
 });

 var div = '<div class="navbar">' + a + '</div>';

 $(".picker-box").append(div);
 };

 p.navEvent = function () {
 var that = this;
 var navBar = $(".navbar");
 var width = navBar.find("a").width();
 var height = navBar.find("a").height();
 navBar.on("touchstart", function (e) {
  $(this).addClass("active");
  that.createLetterPrompt($(e.target).html());
 });

 navBar.on("touchmove", function (e) {
  e.preventDefault();
  var touch = e.originalEvent.touches[0];
  var pos = {"x": touch.pageX, "y": touch.pageY};
  var x = pos.x, y = pos.y;
  $(this).find("a").each(function (i, item) {
  var offset = $(item).offset();
  var left = offset.left, top = offset.top;
  if (x > left && x < (left + width) && y > top && y < (top + height)) {
   location.href = item.href;
   that.changeLetter($(item).html());
  }
  });
 });

 navBar.on("touchend", function () {
  $(this).removeClass("active");
  $(".prompt").hide();
 })
 };

 p.createLetterPrompt = function (letter) {
 var prompt = $(".prompt");
 if (prompt[0]) {
  prompt.show();
 } else {
  var span = "<span class='prompt'>" + letter + "</span>";
  $(".picker-box").append(span);
 }
 };


 p.changeLetter = function (letter) {
 var prompt = $(".prompt");
 prompt.html(letter);
 };

 $.fn.CityPicker = function (options) {
 return new CityPicker(this, options);
 }
}(window.jQuery, window, document));

代码很简单。这边需要提到的一段代码是:

navBar.on("touchmove", function (e) {
 e.preventDefault();
 var touch = e.originalEvent.touches[0];
 var pos = {"x": touch.pageX, "y": touch.pageY};
 var x = pos.x, y = pos.y;
 $(this).find("a").each(function (i, item) {
 var offset = $(item).offset();
 var left = offset.left, top = offset.top;
 if (x > left && x < (left + width) && y > top && y < (top + height)) {
  location.href = item.href;
  that.changeLetter($(item).html());
 }
 });
});

这段是通过字母导航省份的代码。当手指在字母上滑动时,touchmove事件并不能确定当前的字母是哪个,因为e.target永远是touchstart时的那个字母。所以我不得不通过坐标来判断手指位于哪个字母上,这样就导致一个问题,每次滑动都必须遍历26个字母的坐标,这样效率是非常低的,但是目前我也没有好的办法。

该插件的使用方法非常简单:

// html代码
<input type="text" class="city" />
// js代码

$(".city").CityPicker();

demo: http://demo.3water.com/js/2016/cityPicker-master/test.html。最好用手机浏览器或者chrome模拟器打开。

如果有需要的朋友,可以从https://3water.com/jiaoben/430774.html 下载。

Javascript 相关文章推荐
javascript 框架小结 个人工作经验
Jun 13 Javascript
让div层随鼠标移动的实现代码 ie ff
Dec 18 Javascript
Eclipse引入jquery报错如何解决
Dec 01 Javascript
jQuery实现图片走马灯效果的原理分析
Jan 16 Javascript
AngularJS包括详解及示例代码
Aug 17 Javascript
jQuery Dialog 取消右上角删除按钮事件
Sep 07 Javascript
利用JS判断字符串是否含有数字与特殊字符的方法小结
Nov 25 Javascript
JavaScript易错知识点整理
Dec 05 Javascript
JavaScript 禁止用户保存图片的实现代码
Apr 28 Javascript
vue实现图片上传功能
May 28 Javascript
解决vue项目router切换太慢问题
Jul 19 Javascript
JavaScript继承的三种方法实例
May 12 Javascript
AngularJS 2.0新特性有哪些
Feb 18 #Javascript
JavaScript+canvas实现七色板效果实例
Feb 18 #Javascript
javascript结合Flexbox简单实现滑动拼图游戏
Feb 18 #Javascript
Angular发布1.5正式版,专注于向Angular 2的过渡
Feb 18 #Javascript
iscroll.js的上拉下拉刷新时无法回弹的解决方法
Feb 18 #Javascript
javascript每日必学之条件分支
Feb 17 #Javascript
JavaScipt中栈的实现方法
Feb 17 #Javascript
You might like
PHP中的错误处理、异常处理机制分析
2012/05/07 PHP
PHP内置的Math函数效率测试
2014/12/01 PHP
php使用文本统计访问量的方法
2016/05/12 PHP
php文件上传类完整实例
2016/05/14 PHP
HTML-CSS群中单选引发的“事件”
2007/03/05 Javascript
在页面上点击任一链接时触发一个事件的代码
2007/04/07 Javascript
javascript判断移动端访问设备并解析对应CSS的方法
2015/02/05 Javascript
Javascript调用函数方法的几种方式介绍
2015/03/20 Javascript
下雪了 javascript实现雪花飞舞
2020/08/02 Javascript
全面解析Angular中$Apply()及$Digest()的区别
2016/08/04 Javascript
Vue 实用分页paging实例代码
2017/04/12 Javascript
Angularjs cookie 操作实例详解
2017/09/27 Javascript
Vue三层嵌套路由的示例代码
2018/05/05 Javascript
微信小程序实现默认第一个选中变色效果
2018/07/17 Javascript
nodejs读取图片返回给浏览器显示
2019/07/25 NodeJs
react国际化化插件react-i18n-auto使用详解
2020/03/31 Javascript
小谈angular ng deploy的实现
2020/04/07 Javascript
解决vue项目运行提示Warnings while compiling.警告的问题
2020/09/18 Javascript
Python编程实现控制cmd命令行显示颜色的方法示例
2017/08/14 Python
Python利用itchat对微信中好友数据实现简单分析的方法
2017/11/21 Python
用Python解决x的n次方问题
2019/02/08 Python
python查看文件大小和文件夹内容的方法
2019/07/08 Python
Ubuntu16安装Python3.9的实现步骤
2020/12/15 Python
python palywright库基本使用
2021/01/21 Python
西班牙著名的珠宝首饰品牌:P D PAOLA
2018/09/15 全球购物
彪马加拿大官网:PUMA加拿大
2018/10/04 全球购物
锐步英国官网:Reebok英国
2019/11/29 全球购物
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
《王二小》教学反思
2014/02/27 职场文书
机关党员公开承诺书
2014/08/30 职场文书
学生未请假就回家检讨书
2014/09/22 职场文书
2015年入党决心书
2015/02/05 职场文书
专职安全员岗位职责
2015/04/11 职场文书
公司聚餐通知
2015/04/22 职场文书
在 SQL 语句中处理 NULL 值的方法
2021/06/07 SQL Server
python百行代码实现汉服圈图片爬取
2021/11/23 Python