663 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* CityPicker v1.3.2
* https://github.com/tshi0912/citypicker
*
* Copyright (c) 2015-2019 Tao Shi
* Released under the MIT license
*
* Date: 2019-10-19T17:21: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';
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 PROVINCE = 'province';
var CITY = 'city';
var DISTRICT = 'district';
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.codeRender();
this.defineDems();
this.render();
this.bind();
this.active = true;
},
codeRender: function () {
var code = this.$element.attr('code');
var value = this.$element.val();
if (code !== undefined && code !== '' && !isNaN(Number(code))) this.$element.val($.fn.citypicker.getAddressbyCodeId(code));
if (value !== undefined && value !== '' && !isNaN(Number(value))) this.$element.val($.fn.citypicker.getAddressbyCodeId(value));
},
render: function () {
var p = this.getPosition(),
placeholder = this.$element.attr('placeholder') || this.options.placeholder,
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"></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="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 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>';
this.$element.addClass('city-picker-input');
this.$textspan = $(textspan).insertAfter(this.$element);
this.$dropdown = $(dropdown).insertAfter(this.$textspan);
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('/');
$.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(PROVINCE);
this.feedText();
this.feedVal();
},
defineDems: function () {
var stop = false;
$.each([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 $select = $(this).parents('.city-select');
var $active = $select.find('a.active');
var last = $select.next().length === 0;
$active.removeClass('active');
$(this).addClass('active');
if ($active.data('code') !== $(this).data('code')) {
$select.data('item', {
address: $(this).attr('title'), code: $(this).data('code')
});
$(this).trigger(EVENT_CHANGE);
$this.feedText();
$this.feedVal(true);
if (last) {
$this.close();
}
}
}).on('click', '.city-select-tab a', function () {
if (!$(this).hasClass('active')) {
var type = $(this).data('count');
$this.tab(type);
}
}).on('mousedown', function () {
$this.needBlur = false;
});
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)));
}
},
open: function (type) {
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.$province) {
this.$province.off(EVENT_CHANGE, this._changeProvince);
}
if (this.$city) {
this.$city.off(EVENT_CHANGE, this._changeCity);
}
},
getText: function () {
var text = '';
this.$dropdown.find('.city-select')
.each(function () {
var item = $(this).data('item'),
type = $(this).data('count');
if (item) {
text += ($(this).hasClass('province') ? '' : '/') + '<span class="select-item" data-count="' +
type + '" data-code="' + item.code + '">' + item.address + '</span>';
}
});
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');
obj[count] = code;
arr.push(code);
});
return count ? obj[count] : arr.join('/');
},
getVal: function () {
var text = '';
var code = '';
this.$dropdown.find('.city-select')
.each(function () {
var item = $(this).data('item');
if (item) {
code = item.code;
text += ($(this).hasClass('province') ? '' : '/') + item.address;
}
});
return this.options.render == 'code' ? code : text;
},
feedVal: function (trigger) {
this.$element.val(this.getVal());
if (trigger) {
this.$element.trigger('cp:updated');
}
},
output: function (type) {
var options = this.options;
//var placeholders = this.placeholders;
var $select = this['$' + type];
var data = type === PROVINCE ? {} : [];
var item;
var districts;
var code;
var matched = null;
var value;
if (!$select || !$select.length) {
return;
}
item = $select.data('item');
value = (item ? item.address : null) || options[type];
code = (
type === PROVINCE ? 86 :
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;
if ($.isPlainObject(districts)) {
$.each(districts, function (code, address) {
var provs;
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
};
}
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
};
}
data.push({
code: code,
address: address,
selected: address === value
});
}
});
}
$select.html(type === PROVINCE ? this.getProvinceList(data) :
this.getList(data, type));
$select.data('item', matched);
},
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 === 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: true,
render: 'text',//填充为代码还是文本可选code或text
placeholder: '请选择省/市/区',
level: 'district',
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;
};
// 根据code查询地址
$.fn.citypicker.getAddressbyCodeId = function (code_id) {
var city = ChineseDistricts;
var code = city['' + code_id];
var addr = '';
var province = '';
var province_code = '';
var city_str = '';
var county = '';
if (code_id.substring(0, 2) === '44') {
province = '广东省';
province_code = '440000';
} else {
$.each(city['86'], function (i, item) {
$.each(item, function (j, index) {
if (index['code'] === code_id.substring(0, 2) + '0000') {
province = index['address'];
province_code = index['code'];
return false;
}
});
});
}
if (code_id.substring(2, 4).indexOf('00') == -1) {
if (code_id.length > 6) {
var city_code = code_id.substring(0, 6);
if (typeof city[province_code][city_code] !== 'undefined') {
city_str = city[province_code][city_code];
}
}
if (!city_str) {
var city_code = code_id.substring(0, 4) + '00';
if (typeof city[province_code][city_code] === 'undefined') {
city_code = code_id.substring(0, 3) + '100';
}
if (typeof city[province_code][city_code] !== 'undefined') {
city_str = city[province_code][city_code];
}
}
}
if (code === undefined) {
addr = city[city_code][code_id];
return addr = province + '/' + city_str + '/' + addr;
} else {
if (code_id.substring(2, 4).indexOf('00') != -1) {
//440000
return addr = province;
} else {
//440100
var city_city = city[code_id.substring(0, 2) + '0000'];
return addr = province + '/' + city_city[code_id];
}
}
}
$(function () {
$('[data-toggle="city-picker"]').citypicker();
});
});