下面是效果图:
接到需求,地区这边需要多选,原有的插件就不动了,要兼容原来的,还是很烦的,所以在原有的基础上复制一份,重命名city-picker-multi.min.js,
在这个基础上更改。
参考@Karson 的文章
https://ask.fastadmin.net/question/5576.html
在backend-init.js中新增一下内容:
define(['backend'], function (Backend) { require.config({ paths: { 'citypickermulti': '../libs/fastadmin-citypicker/dist/js/city-picker-multi.min', }, shim: { 'citypickermulti': ['citypicker-data', 'css!../libs/fastadmin-citypicker/dist/css/city-picker.css'], } });});
加载这边ok了,那么怎么绑定触发呢?参考city-picker的使用,在require-form.js中新增一下内容
![image.png](//cdn.fastadmin.net/uploads/2019/201901/21/036f07df84616f7c6386737d8152077c)
想要调用的话:
<input id="city-picker" data-rule="required" data-input="range" data-input_val="{$row.ranges}" data-input_address="{$row.range_address}" value="{$row.range_address}" class="form-control" type="text" style="width: 400px" data-toggle="city-picker-multi">
其中:
data-toggle="city-picker-multi" 是触发器了,data-input是生成的隐藏域的name值,提交后用这个name值接收,data-input_val是默认选中的code值,多个值用英文“,”连接,data-input_address和value是默认选中的code值对应的地区名称,用 “/” 连接多个值,注意要和code一一对应,下面是插件的代码:
/*! * CityPicker v1.3.1 * https://github.com/tshi0912/citypicker * * Copyright (c) 2015-2018 Tao Shi * Released under the MIT license * * Date: 2018-09-10T15:57:49.592Z */(function(factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as anonymous module. define(['jquery', 'ChineseDistricts'], factory); } else if (typeof exports === 'object') { // Node / CommonJS factory(require('jquery'), require('ChineseDistricts')); } else { // Browser globals. factory(jQuery, ChineseDistricts); }})(function($, ChineseDistricts) { 'use strict'; // $.post("/api/pub/getcity",function(data){ // ChineseDistricts = data; // },"json"); if (typeof ChineseDistricts === 'undefined') { throw new Error('The file "city-picker.data.js" must be included first!'); } var NAMESPACE = 'citypicker'; var EVENT_CHANGE = 'change.' + NAMESPACE; var COUNTRY = 'country'; var PROVINCE = 'province'; var CITY = 'city'; var DISTRICT = 'district'; Array.prototype.indexOf = function(val, key = '') { for (var i = 0; i < this.length; i++) { if(key != ''){ if(this[i][key] == val) return i; }else{ if (this[i] == val) return i; } } return -1; } Array.prototype.remove = function(val, key = '') { var index = this.indexOf(val, key); if (index > -1) { this.splice(index, 1); } }; function CityPicker(element, options) { this.$element = $(element); this.$dropdown = null; this.options = $.extend({}, CityPicker.DEFAULTS, $.isPlainObject(options) && options); this.active = false; this.dems = []; this.needBlur = false; this.init(); } CityPicker.prototype = { constructor: CityPicker, init: function() { this.defineDems(); this.render(); this.bind(); this.active = true; }, render: function() { var p = this.getPosition(), placeholder = this.$element.attr('placeholder') || this.options.placeholder, valInput = this.$element.data('input') || this.options.input, inputval = this.$element.data('input_val') || this.options.inputval, inputaddress = this.$element.data('input_address') || this.options.inputaddress, textspan = '<span class="city-picker-span" style="' + this.getWidthStyle(p.width) + 'height:' + p.height + 'px;line-height:' + (p.height - 1) + 'px;">' + (placeholder ? '<span class="placeholder">' + placeholder + '</span>' : '') + '<span class="title" style="display:inline-block;width:100%;overflow:hidden;white-space:nowrap;"></span><div class="arrow"></div>' + '</span>', dropdown = '<div class="city-picker-dropdown" style="left:0px;top:100%;' + this.getWidthStyle(p.width, true) + '">' + '<div class="city-select-wrap">' + '<div class="city-select-tab">' + '<a class="active" data-count="country">国家</a>' + (this.includeDem('province') ? '<a data-count="province">省份</a>' : '') + (this.includeDem('city') ? '<a data-count="city">城市</a>' : '') + (this.includeDem('district') ? '<a data-count="district">区县</a>' : '') + '</div>' + '<div class="city-select-content">' + '<div class="city-select country" data-count="country"></div>' + (this.includeDem('province') ? '<div class="city-select province" data-count="province"></div>' : '') + (this.includeDem('city') ? '<div class="city-select city" data-count="city"></div>' : '') + (this.includeDem('district') ? '<div class="city-select district" data-count="district"></div>' : '') + '</div>' + '<div class="city-select-confirm text-center" style="width: 100%;min-height: 10px;background-color: #fff;padding:10px 15px;box-sizing: border-box;">' + '<a class="btn btn-success csc-y" style="margin:0 2px;">确定</a>' + '<a class="btn btn-default csc-n" style="margin:0 2px;">取消</a>' + '</div></div>', inputitem = '<input type="hidden" name="'+valInput+'" value="'+inputval+'" data-address="" id="multiAreaInput" />', multiresdiv = '<div class="'+ (inputaddress ? '' : ' hide ') +' multi-city-res-div">' + (inputaddress ? this.addMultiSpan(inputaddress, inputval) : '') + '</div>'; this.$element.addClass('city-picker-input'); this.$textspan = $(textspan).insertAfter(this.$element); this.$dropdown = $(dropdown).insertAfter(this.$textspan); this.$inputitem = $(inputitem).insertAfter(this.$dropdown); this.$multiresdiv = $(multiresdiv).insertBefore(this.$element); var $select = this.$dropdown.find('.city-select'); // setup this.$province, this.$city and/or this.$district object $.each(this.dems, $.proxy(function(i, type) { this['$' + type] = $select.filter('.' + type + ''); }, this)); this.refresh(); }, refresh: function(force) { // clean the data-item for each $select var $select = this.$dropdown.find('.city-select'); $select.data('item', null); // parse value from value of the target $element var val = this.$element.val() || ''; // val = val.split('/'); val = val.split(','); val = val[0].split(/[/-]/); if(val[0] != '' && val[0] != '全国'){ val.unshift('全国'); } $.each(this.dems, $.proxy(function(i, type) { if (val[i] && i < val.length) { this.options[type] = val[i]; } else if (force) { this.options[type] = ''; } this.output(type); }, this)); this.tab(COUNTRY); // this.tab(PROVINCE); this.feedText(); this.feedVal(); }, defineDems: function() { var stop = false; $.each([COUNTRY, PROVINCE, CITY, DISTRICT], $.proxy(function(i, type) { if (!stop) { this.dems.push(type); } if (type === this.options.level) { stop = true; } }, this)); }, includeDem: function(type) { return $.inArray(type, this.dems) !== -1; }, getPosition: function() { var p, h, w, s, pw; p = this.$element.position(); s = this.getSize(this.$element); h = s.height; w = s.width; if (this.options.responsive) { pw = this.$element.offsetParent().width(); if (pw) { w = w / pw; if (w > 0.99) { w = 1; } w = w * 100 + '%'; } } return { top: p.top || 0, left: p.left || 0, height: h, width: w }; }, getSize: function($dom) { var $wrap, $clone, sizes; if (!$dom.is(':visible')) { $wrap = $("<div />").appendTo($("body")); $wrap.css({ "position": "absolute !important", "visibility": "hidden !important", "display": "block !important" }); $clone = $dom.clone().appendTo($wrap); sizes = { width: $clone.outerWidth(), height: $clone.outerHeight() }; $wrap.remove(); } else { sizes = { width: $dom.outerWidth(), height: $dom.outerHeight() }; } return sizes; }, getWidthStyle: function(w, dropdown) { if (this.options.responsive && !$.isNumeric(w)) { return 'width:' + w + ';'; } else { return 'width:' + (dropdown ? Math.max(320, w) : w) + 'px;'; } }, bind: function() { var $this = this; $(document).on('click', (this._mouteclick = function(e) { var $target = $(e.target); var $dropdown, $span, $input; if ($target.is('.city-picker-span')) { $span = $target; } else if ($target.is('.city-picker-span *')) { $span = $target.parents('.city-picker-span'); } if ($target.is('.city-picker-input')) { $input = $target; } if ($target.is('.city-picker-dropdown')) { $dropdown = $target; } else if ($target.is('.city-picker-dropdown *')) { $dropdown = $target.parents('.city-picker-dropdown'); } if ((!$input && !$span && !$dropdown) || ($span && $span.get(0) !== $this.$textspan.get(0)) || ($input && $input.get(0) !== $this.$element.get(0)) || ($dropdown && $dropdown.get(0) !== $this.$dropdown.get(0))) { $this.close(true); } })); this.$element.on('change', (this._changeElement = $.proxy(function() { this.close(true); this.refresh(true); }, this))).on('focus', (this._focusElement = $.proxy(function() { this.needBlur = true; this.open(); }, this))).on('blur', (this._blurElement = $.proxy(function() { if (this.needBlur) { this.needBlur = false; this.close(true); } }, this))); this.$textspan.on('click', function(e) { var $target = $(e.target), type; $this.needBlur = false; if ($target.is('.select-item')) { type = $target.data('count'); $this.open(type); } else { if ($this.$dropdown.is(':visible')) { $this.close(); } else { $this.open(); } } }).on('mousedown', function() { $this.needBlur = false; }); this.$dropdown.on('click', '.city-select a', function() { var _that = this; var $select = $(this).parents('.city-select'); var $active = $select.find('a.active'); var last = $select.next().length === 0; if ($(this).hasClass('active')) { $(this).removeClass('active'); } else { $(this).addClass('active'); } var dataitem = []; var selectitem = $select.data('item') || []; if (selectitem.length <= 0) { $select.data('item', []); } if ($(this).hasClass('active')) { $select.data('item').push({ address: $(this).attr('title'), code: $(this).data('code') }); } else { selectitem = $select.data('item'); $select.data('item').remove($(_that).attr('title'), 'address'); } $(this).trigger(EVENT_CHANGE); $this.feedText(); $this.feedVal(true); }).on('click', '.city-select-tab a', function() { if (!$(this).hasClass('active')) { var type = $(this).data('count'); $this.tab(type); } }).on('click', '.city-select-confirm .csc-y', function() { var code = $this.getCode("district") || $this.getCode("city") || $this.getCode("province") || $this.getCode('country'); var text = $this.getVal(); var multivalarr = $this.$inputitem.val() ? $this.$inputitem.val().split(',') : []; // console.log(text); var _that = this; if(typeof code != 'undefined' && code.length > 0){ var textarr = text.split(','); var textspan = ''; for (var i = 0; i < code.length; i++) { var isthere = false; $this.$multiresdiv.find('.multi-city-res-span').each(function(){ if($(this).data('code') == code[i]){ isthere = true; } }); if(isthere === false){ multivalarr.push(code[i]); $this.$inputitem.val(multivalarr.join()); textspan += ' <span class="multi-city-res-span" style="margin:1px 2px;background-color:#eee;" data-code="'+code[i]+'" data-address="' + textarr[i] + '"><font color="#f00" class="del-multi-span" style="cursor:pointer;font-weight:bolder;"> X </font>' + textarr[i] + '</span> '; } } $this.$multiresdiv.removeClass('hide'); $(textspan).appendTo($this.$multiresdiv); } $this.close(); }).on('click', '.city-select-confirm .csc-n', function() { $this.close(); }).on('mousedown', function() { $this.needBlur = false; }); this.$multiresdiv.on('click', '.del-multi-span', function(){ var multispan = $(this).closest('span'); var thiscode = multispan.data('code'); var multivalarr = $this.$inputitem.val() ? $this.$inputitem.val().split(',') : []; for (var i = 0; i < multivalarr.length; i++) { // console.log({'multival': multivalarr[i], 'thiscode': thiscode}); if(parseInt(multivalarr[i]) == thiscode){ multivalarr.splice(i, 1); } } multispan.remove(); $this.$inputitem.val(multivalarr); if($this.$multiresdiv.find('.multi-city-res-span').length <= 0){ $this.$multiresdiv.addClass('hide'); } }); if (this.$country) { this.$country.on(EVENT_CHANGE, (this._changeCountry = $.proxy(function() { this.output(PROVINCE) this.output(CITY); this.output(DISTRICT); // this.tab(PROVINCE); }, this))); } if (this.$province) { this.$province.on(EVENT_CHANGE, (this._changeProvince = $.proxy(function() { this.output(CITY); this.output(DISTRICT); // this.tab(CITY); }, this))); } if (this.$city) { this.$city.on(EVENT_CHANGE, (this._changeCity = $.proxy(function() { this.output(DISTRICT); // this.tab(DISTRICT); }, this))); } if (this.$inputval) { } }, open: function(type) { type = type || COUNTRY; // type = type || PROVINCE; this.$dropdown.show(); this.$textspan.addClass('open').addClass('focus'); this.tab(type); }, close: function(blur) { this.$dropdown.hide(); this.$textspan.removeClass('open'); if (blur) { this.$textspan.removeClass('focus'); } }, unbind: function() { $(document).off('click', this._mouteclick); this.$element.off('change', this._changeElement); this.$element.off('focus', this._focusElement); this.$element.off('blur', this._blurElement); this.$textspan.off('click'); this.$textspan.off('mousedown'); this.$dropdown.off('click'); this.$dropdown.off('mousedown'); if (this.$country) { this.$country.off(EVENT_CHANGE, this._changeCountry); } if (this.$province) { this.$province.off(EVENT_CHANGE, this._changeProvince); } if (this.$city) { this.$city.off(EVENT_CHANGE, this._changeCity); } }, getText: function() { var text = ''; var spantextarr = []; var eachindex = 0; this.$dropdown.find('.city-select') .each(function() { var _that = this; var spanresarr = []; var item = $(this).data('item'); console.log(item) var type = $(this).data('count'); var spantext; if (item) { $.each(item, function(index, itemdata) { spantext = '<span class="select-item" data-count="' + type + '" data-code="' + itemdata.code + '">' + itemdata.address + '</span>'; spanresarr.push(spantext); }) spantextarr.push(spanresarr) } }); var zuhe = this.zuHe(spantextarr); if (typeof zuhe != 'undefined') { text = zuhe.join(); } return text; }, getPlaceHolder: function() { return this.$element.attr('placeholder') || this.options.placeholder; }, feedText: function() { var text = this.getText(); if (text) { this.$textspan.find('>.placeholder').hide(); this.$textspan.find('>.title').html(this.getText()).show(); } else { this.$textspan.find('>.placeholder').text(this.getPlaceHolder()).show(); this.$textspan.find('>.title').html('').hide(); } }, getCode: function(count) { var obj = {}, arr = []; this.$textspan.find('.select-item') .each(function() { var code = $(this).data('code'); var count = $(this).data('count'); if(! (count in obj)){ obj[count] = []; } obj[count].push(code); arr.push(code); }); // var res = count ? obj[count] : arr.join('/'); // console.log(res); return count ? obj[count] : arr.join('/'); }, getVal: function() { var text = ''; var textarr = []; var eachindex = 0; this.$dropdown.find('.city-select') .each(function() { var _that = this; var resarr = []; var item = $(this).data('item'); // console.log(item); if (item) { $.each(item, function(index, itemdata) { resarr.push(itemdata.address); }) textarr.push(resarr) } }); var zuhe = this.zuHe(textarr); if (typeof zuhe != 'undefined') { text = zuhe.join(); } return text; }, feedVal: function(trigger) { this.$element.val(this.getVal()); if (trigger) { this.$element.trigger('cp:updated'); } }, zuHe: function(selectaddress) { var heads = selectaddress[0]; for (var i = 1, len = selectaddress.length; i < len; i++) { if (selectaddress[i].length) { heads = this.addNewType(heads, selectaddress[i]); } } return heads; }, addNewType: function(heads, choices) { var result = []; for (var i = 0, len = heads.length; i < len; i++) { for (var j = 0, lenj = choices.length; j < lenj; j++) { result.push(heads[i] + '/' + choices[j]); } } return result; }, indexOfArr: function(arr, val) { for (var i = 0; i < arr.length; i++) { if (arr[i] == val) { return i; } } return -1; }, removeArrVal: function(arr, val) { var index = this.indexOfArr(arr, val); if (index > -1) { arr.splice(index, 1); } return arr; }, addMultiSpan: function(inputaddress, inputval) { var text = ''; if(inputaddress){ var inputaddarr = inputaddress ? inputaddress.toString().split(',') : []; var inputvalarr = inputval ? inputval.toString().split(',') : []; var textarr = []; for (var i = 0; i < inputaddarr.length; i++) { textarr.push(' <span class="multi-city-res-span" style="margin:1px 2px;background-color:#eee;" data-code="'+inputvalarr[i]+'" data-address="' + inputaddarr[i] + '"><font color="#f00" class="del-multi-span" style="cursor:pointer;font-weight:bolder;"> X </font>' + inputaddarr[i] + '</span> '); } text = textarr.join(','); } return text; }, output: function(type) { var options = this.options; //var placeholders = this.placeholders; var $select = this['$' + type]; // var data = type === COUNTRY ? {} : []; var data = type === PROVINCE ? {} : []; var item; var districts; var code; var matched = null; var value; var ismore = false; if (!$select || !$select.length) { return; } item = $select.data('item'); value = (item ? item.address : null) || options[type]; code = ( type === COUNTRY ? 0 : // type === PROVINCE ? 86 : type === PROVINCE ? this.$country && this.$country.find('.active').data('code') : type === CITY ? this.$province && this.$province.find('.active').data('code') : type === DISTRICT ? this.$city && this.$city.find('.active').data('code') : code ); districts = $.isNumeric(code) ? ChineseDistricts[code] : null; ismore = ( type === COUNTRY ? false : // type === PROVINCE ? 86 : type === PROVINCE ? (this.$country.find('.active').length > 1) : type === CITY ? (this.$province.find('.active').length > 1) : type === DISTRICT ? (this.$city.find('.active').length > 1) : ismore ); if (ismore == true) { districts = {}; } if ($.isPlainObject(districts)) { $.each(districts, function(code, address) { var provs; if (type === COUNTRY) { if (address === value) { // matched = { // code: code, // address: address // }; matched = []; matched.push({ code: code, address: address }); } data.push({ code: code, address: address, selected: address === value }); } else if (type === PROVINCE) { provs = []; for (var i = 0; i < address.length; i++) { if (address[i].address === value) { // matched = { // code: address[i].code, // address: address[i].address // }; matched = []; matched.push({ code: address[i].code, address: address[i].address }); } provs.push({ code: address[i].code, address: address[i].address, selected: address[i].address === value }); } data[code] = provs; } else { if (address === value) { // matched = { // code: code, // address: address // }; matched = []; matched.push({ code: code, address: address }); } data.push({ code: code, address: address, selected: address === value }); } }); } $select.html(type === COUNTRY ? this.getCountryList(data, type) : type === PROVINCE ? this.getProvinceList(data) : this.getList(data, type)); $select.data('item', matched); }, getCountryList: function(data, type) { var list = [], $this = this, simple = this.options.simple; list.push('<dl class="clearfix"><dd>'); $.each(data, function(i, n) { list.push( '<a' + ' title="' + (n.address || '') + '"' + ' data-code="' + (n.code || '') + '"' + ' class="' + (n.selected ? ' active' : '') + '">' + (simple ? $this.simplize(n.address, type) : n.address) + '</a>'); }); list.push('</dd></dl>'); return list.join(''); }, getProvinceList: function(data) { var list = [], $this = this, simple = this.options.simple; $.each(data, function(i, n) { list.push('<dl class="clearfix">'); list.push('<dt>' + i + '</dt><dd>'); $.each(n, function(j, m) { list.push( '<a' + ' title="' + (m.address || '') + '"' + ' data-code="' + (m.code || '') + '"' + ' class="' + (m.selected ? ' active' : '') + '">' + (simple ? $this.simplize(m.address, PROVINCE) : m.address) + '</a>'); }); list.push('</dd></dl>'); }); return list.join(''); }, getList: function(data, type) { var list = [], $this = this, simple = this.options.simple; list.push('<dl class="clearfix"><dd>'); $.each(data, function(i, n) { list.push( '<a' + ' title="' + (n.address || '') + '"' + ' data-code="' + (n.code || '') + '"' + ' class="' + (n.selected ? ' active' : '') + '">' + (simple ? $this.simplize(n.address, type) : n.address) + '</a>'); }); list.push('</dd></dl>'); return list.join(''); }, simplize: function(address, type) { address = address || ''; if (type === COUNTRY) { return address.replace(/[国家,省,市,自治区]/g, ''); } else if (type === PROVINCE) { return address.replace(/[省,市,自治区,壮族,回族,维吾尔]/g, ''); } else if (type === CITY) { return address.replace(/[市,地区,回族,蒙古,苗族,白族,傣族,景颇族,藏族,彝族,壮族,傈僳族,布依族,侗族]/g, '') .replace('哈萨克', '').replace('自治州', '').replace(/自治县/, ''); } else if (type === DISTRICT) { return address.length > 2 ? address.replace(/[市,区,县,旗]/g, '') : address; } }, tab: function(type) { var $selects = this.$dropdown.find('.city-select'); var $tabs = this.$dropdown.find('.city-select-tab > a'); var $select = this['$' + type]; var $tab = this.$dropdown.find('.city-select-tab > a[data-count="' + type + '"]'); if ($select) { $selects.hide(); $select.show(); $tabs.removeClass('active'); $tab.addClass('active'); } }, reset: function() { this.$element.val(null).trigger('change'); }, destroy: function() { this.unbind(); this.$element.removeData(NAMESPACE).removeClass('city-picker-input'); this.$textspan.remove(); this.$dropdown.remove(); } }; CityPicker.DEFAULTS = { simple: false, responsive: false, placeholder: '请选择全国省/市/区', input: 'area', inputval: '', inputaddress: '', level: 'district', country: '', province: '', city: '', district: '' }; CityPicker.setDefaults = function(options) { $.extend(CityPicker.DEFAULTS, options); }; // Save the other citypicker CityPicker.other = $.fn.citypicker; // Register as jQuery plugin $.fn.citypicker = function(option) { var args = [].slice.call(arguments, 1); return this.each(function() { var $this = $(this); var data = $this.data(NAMESPACE); var options; var fn; if (!data) { if (/destroy/.test(option)) { return; } options = $.extend({}, $this.data(), $.isPlainObject(option) && option); $this.data(NAMESPACE, (data = new CityPicker(this, options))); } if (typeof option === 'string' && $.isFunction(fn = data[option])) { fn.apply(data, args); } }); }; $.fn.citypicker.Constructor = CityPicker; $.fn.citypicker.setDefaults = CityPicker.setDefaults; // No conflict $.fn.citypicker.noConflict = function() { $.fn.citypicker = CityPicker.other; return this; }; $(function() { $('[data-toggle="city-picker-multi"]').citypicker(); });});
以上代码只是初步满足了需求,对于原插件的其他功能,并没有完全改造,后期遇到再调整。
希望以上内容对你有所帮助!如果还有其他问题,请随时提问。 各类知识收集 拥有多年CMS企业建站经验,对 iCMS, Fastadmin, ClassCMS, LeCMS, PbootCMS, PHPCMS, 易优CMS, YzmCMS, 讯睿CMS, 极致CMS, Wordpress, HkCMS, YznCMS, WellCMS, ThinkCMF, 等各类cms的相互转化,程序开发,网站制作,bug修复,程序杀毒,插件定制都可以提供最佳解决方案。