给Gravity Forms表单添加定制级联菜单,中国城市选择选项

Gravity Forms(重力表单插件,本文简称GF)是一款公认十分强大的WordPress表单插件,不过其强大之处在我看来并不是选项多,操作简单等常规“小儿科”特性,这一点其实很多其他的表单插件都能做到。GF强大之处在于它提供了十分周全的API和文档让开发者能做进一步开发,满足用户更复杂的业务需求。这一点恐怕没有其他竞品可以与之相比。

表单插件虽然多,提供级联下拉菜单的表单插件恐怕就很少了。GF本身也没有提供,不过用户可以通过逻辑功能绕道在后台实现简单的级联菜单,方法是先放入一个一级菜单,再放入N个二级菜单,二级菜单默认全部隐藏,根据一级菜单的选项来显示对应二级菜单。这种实现方法比较直观,但如果一级菜单选项很多,那添加和维护就很吃力了。于是我尝试用GF提供的API自己定制一个级联菜单,选择中国所有34省级行政区下的对应城市/区。总共34个一级选项,五百多个城市子选项,这要在后台一一添加可真的是非常麻烦了。

先上结果图:
给Gravity Forms表单添加定制级联菜单,中国城市选择选项

JS代码,保存到新建的JS文件中:

var multiSelect = new Object({
	dataList : {
		'安徽' : ['合肥','安庆','蚌埠','亳州','巢湖','滁州','阜阳','贵池','淮北','淮化','淮南','黄山','九华山','六安','马鞍山','宿州','铜陵','屯溪','芜湖','宣城'],
		'北京' : ['东城','西城','崇文','宣武','朝阳','丰台','石景山','海淀','门头沟','房山','通州','顺义','昌平','大兴','平谷','怀柔','密云','延庆'],
		'重庆' : ['万州','涪陵','渝中','大渡','江北','沙坪','九龙','南岸','北碚','万盛','双挢','渝北','巴南','黔江','长寿','綦江','潼南','铜梁','大足','荣昌','壁山','梁平','城口','丰都','垫江','武隆','忠县','开县','云阳','奉节','巫山','巫溪','石柱','秀山','酉阳','彭水','江津','合川','永川','南川'],
		'福建' : ['福州','福安','龙岩','南平','宁德','莆田','泉州','三明','邵武','石狮','晋江','永安','武夷山','厦门','漳州'],
		'甘肃' : ['兰州','白银','定西','敦煌','甘南','金昌','酒泉','临夏','平凉','天水','武都','武威','西峰','嘉峪关','张掖'],
		'广东' : ['广州','潮阳','潮州','澄海','东莞','佛山','河源','惠州','江门','揭阳','开平','茂名','梅州','清远','汕头','汕尾','韶关','深圳','顺德','阳江','英德','云浮','增城','湛江','肇庆','中山','珠海'],
		'广西' : ['南宁','百色','北海','桂林','防城港','河池','贺州','柳州','来宾','钦州','梧州','贵港','玉林'],
		'贵州' : ['贵阳','安顺','毕节','都匀','凯里','六盘水','铜仁','兴义','玉屏','遵义'],
		'海南' : ['海口','三亚','五指山','琼海','儋州','文昌','万宁','东方','定安','屯昌','澄迈','临高','万宁','白沙黎族','昌江黎族','乐东黎族','陵水黎族','保亭黎族','琼中黎族','西沙群岛','南沙群岛','中沙群岛'],
		'河北' : ['石家庄','保定','北戴河','沧州','承德','丰润','邯郸','衡水','廊坊','南戴河','秦皇岛','唐山','新城','邢台','张家口'],
		'黑龙江' : ['哈尔滨','北安','大庆','大兴安岭','鹤岗','黑河','佳木斯','鸡西','牡丹江','齐齐哈尔','七台河','双鸭山','绥化','伊春'],
		'河南' : ['郑州','安阳','鹤壁','潢川','焦作','济源','开封','漯河','洛阳','南阳','平顶山','濮阳','三门峡','商丘','新乡','信阳','许昌','周口','驻马店'],
		'香港' : ['香港','九龙','新界'],
		'湖北' : ['武汉','恩施','鄂州','黄冈','黄石','荆门','荆州','潜江','十堰','随州','武穴','仙桃','咸宁','襄阳','襄樊','孝感','宜昌'],
		'湖南' : ['长沙','常德','郴州','衡阳','怀化','吉首','娄底','邵阳','湘潭','益阳','岳阳','永州','张家界','株洲'],
		'江苏' : ['南京','常熟','常州','海门','淮安','江都','江阴','昆山','连云港','南通','启东','沭阳','宿迁','苏州','太仓','泰州','同里','无锡','徐州','盐城','扬州','宜兴','仪征','张家港','镇江','周庄'],
		'江西' : ['南昌','抚州','赣州','吉安','景德镇','井冈山','九江','庐山','萍乡','上饶','新余','宜春','鹰潭'],
		'吉林' : ['长春','白城','白山','珲春','辽源','梅河','吉林','四平','松原','通化','延吉'],
		'辽宁' : ['沈阳','鞍山','本溪','朝阳','大连','丹东','抚顺','阜新','葫芦岛','锦州','辽阳','盘锦','铁岭','营口'],
		'澳门' : ['澳门'],
		'内蒙古' : ['呼和浩特','阿拉善盟','包头','赤峰','东胜','海拉尔','集宁','临河','通辽','乌海','乌兰浩特','锡林浩特'],
		'宁夏' : ['银川','固原','中卫','石嘴山','吴忠'],
		'青海' : ['西宁','德令哈','格尔木','共和','海东','海晏','玛沁','同仁','玉树'],
		'山东' : ['济南','滨州','兖州','德州','东营','菏泽','济宁','莱芜','聊城','临沂','蓬莱','青岛','曲阜','日照','泰安','潍坊','威海','烟台','枣庄','淄博'],
		'上海' : ['崇明','黄浦','卢湾','徐汇','长宁','静安','普陀','闸北','虹口','杨浦','闵行','宝山','嘉定','浦东','金山','松江','青浦','南汇','奉贤','朱家角'],
		'山西' : ['太原','长治','大同','候马','晋城','离石','临汾','宁武','朔州','忻州','阳泉','榆次','运城'],
		'陕西' : ['西安','安康','宝鸡','汉中','渭南','商州','绥德','铜川','咸阳','延安','榆林'],
		'四川' : ['成都','巴中','达州','德阳','都江堰','峨眉山','涪陵','广安','广元','九寨沟','康定','乐山','泸州','马尔康','绵阳','眉山','南充','内江','攀枝花','遂宁','汶川','西昌','雅安','宜宾','自贡','资阳'],
		'台湾' : ['台北','基隆','台南','台中','高雄','屏东','南投','云林','新竹','彰化','苗栗','嘉义','花莲','桃园','宜兰','台东','金门','马祖','澎湖','其它'],
		'天津' : ['天津','和平','东丽','河东','西青','河西','津南','南开','北辰','河北','武清','红挢','塘沽','汉沽','大港','宁河','静海','宝坻','蓟县'],
		'新疆' : ['乌鲁木齐','阿克苏','阿勒泰','阿图什','博乐','昌吉','东山','哈密','和田','喀什','克拉玛依','库车','库尔勒','奎屯','石河子','塔城','吐鲁番','伊宁'],
		'西藏' : ['拉萨','阿里','昌都','林芝','那曲','日喀则','山南'],
		'云南' : ['昆明','大理','保山','楚雄','大理','东川','个旧','景洪','开远','临沧','丽江','六库','潞西','曲靖','思茅','文山','西双版','玉溪','中甸','昭通'],
		'浙江' : ['杭州','安吉','慈溪','定海','奉化','海盐','黄岩','湖州','嘉兴','金华','临安','临海','丽水','宁波','瓯海','平湖','千岛湖','衢州','江山','瑞安','绍兴','嵊州','台州','温岭','温州','余姚','舟山'],
		},
	placeholder1 : "请选择省份",
	placeholder2 : "请选择城市",
 
	initFields : function( firstField , secondField ){
		var dataList = this.dataList;
		var placeholder1 = this.placeholder1;
		var placeholder2 = this.placeholder2;
		firstField.add(new Option( placeholder1 ,""));
		secondField.add(new Option( placeholder2 ,""));
		Object.keys( dataList ).forEach(function(val){
			firstField.add(new Option(val,val))
		});
		firstField.selectedIndex =0;
		firstField.addEventListener("change", function(){
			var provinceVal = this.options[this.selectedIndex].value;
			secondField.options.length=0; //remove all cities
			secondField.add(new Option( placeholder2 ,""));
			dataList[provinceVal].forEach(function(val){
				secondField.add(new Option(val,val))
			});
			secondField.nextSibling.value = provinceVal;
		}, false);
		secondField.addEventListener("change", function(){
			var cityVal = this.options[this.selectedIndex].value;
			secondField.nextSibling.value = firstField.options[firstField.selectedIndex].value + "-" + cityVal;
		}, false);
	},
 
	countSubItems : function(){
		var countNum = 0;
		var dataList = this.dataList;
		Object.keys( dataList ).forEach(function(val){
			countNum+= dataList[val].length;
		});
		return countNum;
	}
});

PHP代码,放到主题function.php中

//gravityforms implement China city select field
add_filter( 'gform_field_content_1_4', 'brain1981_gf_city_select', 10, 5 );
function brain1981_gf_city_select( $content, $field, $value, $lead_id, $form_id ) {
	//避免在查询后台看到页面内容
	if ( $field->is_entry_detail_edit() ) {
		return $content;
	} elseif ( $field->is_entry_detail() ) {
		return $content;
	}
	$content ="<label class='gfield_label' for='input_{$form_id}_{$field->id}'>{$field->label}</label>";
	$content =$content."<div class='ginput_container ginput_container_select ginput_container_city'>";
	$content =$content."<select name='gf_province' id='gf_province' value='' class='middle gfield_select gf_province'></select>";
	$content =$content."<select name='gf_city' id='gf_city' value='' class='middle gfield_select gf_city'></select>";
	$content =$content."<input type='hidden' name='input_{$field->id}' id='input_{$form_id}_{$field->id}' value='' class='gform_hidden'>";
	$content =$content."</div>";
	$content =$content."<script src='".get_template_directory_uri()."/js/form-china-cities.js' type='text/javascript'></script>"; //JS代码存放路径
	$content =$content."<script>var newSelectField = Object.create(multiSelect); newSelectField.initFields( document.getElementById('gf_province') , document.getElementById('gf_city') )</script>";
	return $content;
}

实现思路就是用自己的级联菜单去替换GF中已经添加的某个字段,以上代码中的第2行“gform_field_content_1_4″,其中的1是需要添加此字段的表单ID号,4是要替换的字段在表单中的序号。这两个数字需要根据实际情况修改。gform_field_content_{form id}_{field id} 是GF一个用处很大的钩子,用它可以对表单内容进行各种自由发挥。

另外,修改JS代码中的dataList对象中的数据,就能改出其他任意的二级级联菜单。
如果要统计一共有多少个字选项,前端执行

newSelectField.countSubItems();

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/2048.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。