allocatr/public/assets/libs/fastadmin-citypicker/dist/js/city-picker.min.js
2025-07-16 15:56:52 +08:00

474 lines
21 KiB
JavaScript
Executable File
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) {
define(["jquery", "ChineseDistricts"], factory)
} else if (typeof exports === "object") {
factory(require("jquery"), require("ChineseDistricts"))
} else {
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('100%') + "height:" + p.height + "px;line-height:" + (p.height - 1) + 'px;">' + (placeholder ? '<span class="placeholder">' + placeholder + "</span>" : "") + '<span class="title"></span><div class="arrow"></div><div class="close">×</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");
$.each(this.dems, $.proxy(function (i, type) {
this["$" + type] = $select.filter("." + type + "")
}, this));
this.refresh()
}, refresh: function (force) {
var $select = this.$dropdown.find(".city-select");
$select.data("item", null);
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 > .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($target.is(".close")){
$this.reset()
}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 $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").trigger("cp:updated")
}, 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",
placeholder: "请选择省/市/区",
level: "district",
province: "",
city: "",
district: ""
};
CityPicker.setDefaults = function (options) {
$.extend(CityPicker.DEFAULTS, options)
};
CityPicker.other = $.fn.citypicker;
$.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;
$.fn.citypicker.noConflict = function () {
$.fn.citypicker = CityPicker.other;
return this
};
$.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) {
return addr = province
} else {
var city_city = city[code_id.substring(0, 2) + "0000"];
return addr = province + "/" + city_city[code_id]
}
}
};
$(function () {
$('[data-toggle="city-picker"]').citypicker()
})
});