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的键盘控制事件说明
Apr 15 Javascript
jQuery 学习入门篇附实例代码
Mar 16 Javascript
Jquery中删除元素的实现代码
Dec 29 Javascript
document.write的几点使用心得
May 14 Javascript
node.js中的fs.fsync方法使用说明
Dec 15 Javascript
input输入框鼠标焦点提示信息
Mar 17 Javascript
JS实现为表格动态添加标题的方法
Mar 31 Javascript
Ionic3 UI组件之Gallery Modal详解
Jun 07 Javascript
javascript trie前缀树的示例
Jan 29 Javascript
详解Chai.js断言库API中文文档
Jan 31 Javascript
JavaScript 中定义函数用 var foo = function () {} 和 function foo()区别介绍
Mar 01 Javascript
js实现的订阅发布者模式简单示例
Mar 14 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
新浪微博API开发简介之用户授权(PHP基础篇)
2011/09/25 PHP
php中导出数据到excel时数字变为科学计数的解决方法
2013/02/03 PHP
解析Extjs与php数据交互(增删查改)
2013/06/25 PHP
PHP自动生成后台导航网址的最佳方法
2013/08/27 PHP
PHP+jquery实时显示网站在线人数的方法
2015/01/04 PHP
thinkphp5使用无限极分类
2019/02/18 PHP
在网页里看flash的trace数据的js类
2009/01/10 Javascript
几个有趣的Javascript Hack
2010/07/24 Javascript
JQuery触发radio或checkbox的change事件
2012/12/18 Javascript
Javacript实现颜色梯度变化和渐变的效果代码
2013/05/31 Javascript
SOSO地图JS画出标注和中心点以html形式运行
2013/08/09 Javascript
一个简单的jquery进度条示例
2014/04/28 Javascript
Nodejs进阶:基于express+multer的文件上传实例
2016/11/21 NodeJs
vue2利用Bus.js如何实现非父子组件通信详解
2017/08/25 Javascript
vue2 router 动态传参,多个参数的实例
2017/11/10 Javascript
angular json对象push到数组中的方法
2018/02/27 Javascript
Vue 项目中遇到的跨域问题及解决方法(后台php)
2018/03/28 Javascript
详解webpack模块化管理和打包工具
2018/04/21 Javascript
JS动态图片的实现方法完整示例
2020/01/13 Javascript
js String.prototype.trim字符去前后空格的扩展
2020/08/23 Javascript
使用Python编写爬虫的基本模块及框架使用指南
2016/01/20 Python
python3 实现的人人影视网站自动签到
2016/06/19 Python
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
让Python更加充分的使用Sqlite3
2017/12/11 Python
Python人脸识别初探
2017/12/21 Python
python实现加密的方式总结
2020/01/19 Python
python异常处理try except过程解析
2020/02/03 Python
Jupyter加载文件的实现方法
2020/04/14 Python
python 实现仿微信聊天时间格式化显示的代码
2020/04/17 Python
英国航空官网:British Airways
2016/09/11 全球购物
世界上最大的隐形眼镜商店:1-800 Contacts
2018/11/03 全球购物
Sarenza德国:法国最大的时尚鞋和包包网上商店
2019/06/08 全球购物
Delphi软件工程师试题
2013/01/29 面试题
家长对孩子的感言
2014/03/10 职场文书
总经理检讨书
2014/09/15 职场文书
出差报告范文
2014/11/06 职场文书