define(function (require, exports) { var $html = '

最近查询

TEST

常用城市

'; var selector; var data = require("../data.js"); var cityMap = data.cities; var citydata = data.citydata.data; var popcity = data.citydata.popcity; var maxRecentCity = 8; var sessMgr = require("../account/sessionMgr.js"); var CitySelector = function (options) { var that = this; var dom = $("#city_selector"); var currentList = null; var currentPage = 1; var totalPage = 1; var pageSize = options.rows * 4; var target = null; var prevTab = null; var searchKey; var tplRecentCity = doT.template("{{~it:c:i}}
{{!c.n}}
{{~}}"); var cp; var container = $("#city_selector"); var initRecentCity = function () { cp = sessMgr.current; container.find("dd").remove(); if (!cp || !cp.recentCity) return; var cities = _.filter(cp.recentCity.map(function (e) { return cityMap[e]; }), function (e) { return e != null; }); container.find("dl").html(tplRecentCity(cities)); }; initRecentCity(); sessMgr.on("sessionChanged", initRecentCity); this.addCityToRecent = function (code) { if (!code || !cp) return; cp.recentCity = cp.recentCity || []; var idx = _.indexOf(cp.recentCity, code); if (idx != -1) { return; } container.find("dd[data-code='" + code + "']").remove(); cp.recentCity.unshift(code); sessMgr.save(); container.find("dl").prepend(tplRecentCity([cityMap[code]])); }; that.findExtractCity = function (val) { if (!val) return null; if (cityMap[val]) return cityMap[val]; for (var c in cityMap) { var city = cityMap[c]; if (city.p === val || city.c === val || city.n === val) return city; } return null; }; that.getSelectedCity = function () { var ele = $(this); var val = ele.val(); var city = null; //取得当前选择的城市。逻辑:如果有输入内容,则查找对应的城市是否存在,存在则直接返回; //否则如果当前输入不为空,则找已选择的,有则返回,没有则取列表第一个返回; //如果都无法返回,则返回null if (val) { city = that.findExtractCity(val); } if (city === null) { //查找已经选中的 var e = dom.find("dd.selected[data-code]:visible, li.selected[data-code]:visible"); if (e.length) { var code = e.attr("data-code"); city = that.findExtractCity(code); } } if (city === null) { var nodes = that.currentShownCities; if (nodes.length) { city = that.findExtractCity(nodes.eq(0).attr("data-code")); } } return city; }; that.performSearch = function () { target = $(this); var key = target.val().replace(/\s/g, ""); if (key === searchKey) return; searchKey = key; if (!key) { that.switchTab(prevTab); return; } //清空选择 that.switchTab(); dom.find(".city-search").show().find(">p").html("搜索“" + key + "”"); //搜索城市 key = key.toUpperCase(); var lkey = key.toLowerCase(); currentList = _.filter(_.values(cityMap), function (e) { return e.p.indexOf(lkey) != -1 || e.n.indexOf(key) != -1 || e.c.indexOf(key) != -1 || e.h.indexOf(lkey) != -1; }); currentPage = 0; totalPage = Math.ceil(currentList.length / pageSize); that.renderPage(1); }; that.showPopup = function (ele) { if (selector.isVisible) return; searchKey = null; that.switchTab(dom.find(".city-tab-nav li:first")); dom.find(".city-list-container li, dd[data-code]").removeClass("selected"); var offset = ele.offset(); dom.css({ left: offset.left + "px", top: (offset.top + ele.height()) + "px" }); dom.addClass("open"); target = ele; }; that.hidePopup = function (force) { dom.removeClass("open"); //验证 var str = target.val(); var city = that.findExtractCity(str); if (!city) { target.val(""); target.attr("data-code", ""); } else { target.val(city.n); target.attr("data-code", city.c); } target[0].dispatchEvent(new UIEvent("change")); if (force) { dom.css("top", "-2000px"); } }; that.switchTab = function (tab) { dom.find(".city-tab-nav li").removeClass("selected"); dom.find(".city-search, .city-pop, .recent-city-list").hide(); if (!tab) return; tab.addClass("selected"); prevTab = tab; var code = tab.attr("data-code"); currentPage = 0; if (code) { dom.find(".city-search>p").html("站点列表"); currentList = _.values(citydata[code]); totalPage = Math.ceil(currentList.length / pageSize); that.renderPage(1); dom.find(".city-search").show(); } else { currentList = null; dom.find(".city-pop, .recent-city-list").show(); } dom.find(".city-list-container ul, dd[data-code]").removeClass("selected"); that.currentShownCities = null; }; that.renderPage = function (page) { /// 切换当前的分页 if (page < 1 || page === currentPage || page > totalPage) return; currentPage = page; //绑定数据 var html = []; var listCount = 0; for (var i = (currentPage - 1) * pageSize; i < currentPage * pageSize && i < currentList.length; i++) { var city = currentList[i]; listCount++; html.push("
  • " + city.n + "
  • "); } if (listCount % 4 !== 0) { for (var i = 0; i < 4 - listCount % 4; i++) { html.push("
  • "); } } dom.find(".city-search ul").empty().append(html.join("")); //上一页下一页可用性 $("button.city-prev")[0].disabled = currentPage <= 1; $("button.city-next")[0].disabled = currentPage >= totalPage - 1; that.currentShownCities = null; }; that.showNextPage = function () { that.renderPage(currentPage + 1); }; that.showPrevPage = function () { that.renderPage(currentPage - 1); }; that.selectNext = function (offset) { offset = offset || 1; //当前的列表 var eles = dom.find("div.recent-city-list:visible dd[data-code], ul.city-list-container:visible li[data-code]"); var current = eles.filter(".selected"); var nextSelect = null; if (!current.length) { //尚没有选择 if (offset > 0) { //向下移动,则默认选择第一个 (nextSelect = eles.first()).addClass("selected"); } else { (nextSelect = eles.last()).addClass("selected"); } } else { var index = eles.index(current); index += offset; if (index < 0) { if (currentPage > 1) { that.showPrevPage(); (nextSelect = dom.find("div.city-search ul.city-list-container li[data-code]:last")).addClass("selected"); } } else if (index >= eles.length) { if (currentPage < totalPage) { that.showNextPage(); (nextSelect = dom.find("div.city-search ul.city-list-container li[data-code]:first")).addClass("selected"); } } else { current.removeClass("selected"); nextSelect = eles.eq(index).addClass("selected"); } } if (nextSelect) { that.selectToTarget(nextSelect.attr("data-code")); } }; dom.find("button.city-prev").click(that.showPrevPage); dom.find("button.city-next").click(that.showNextPage); Object.defineProperty(this, "isVisible", { get: function () { return dom.is(":visible"); } }); //当前显示的城市节点 var _currnetShownNodes; Object.defineProperty(this, "currentShownCities", { get: function () { return _currnetShownNodes || (_currnetShownNodes = dom.find("div.recent-city-list:visible dd[data-code], ul.city-list-container:visible li[data-code]")); }, set: function (value) { _currnetShownNodes = value; } }); dom.find(".city-tab-nav li").click(function () { var tab = $(this); if (tab.hasClass("selected")) return; selector.switchTab(tab); }); that.selectToTarget = function (city, ele) { ele = ele || target; if (!ele) return; if (typeof (city) === "string") city = that.findExtractCity(city); if (!city) city = that.getSelectedCity.call(ele); if (!city) return; ele.data("data-code", city.c); ele.val(city.n); var ce = new UIEvent("change"); ele[0].dispatchEvent(ce); }; $(document).on("click", ".recent-city-list dd[data-code], .city-list-container li[data-code]", function () { //选定城市 that.selectToTarget(this.dataset.code); that.hidePopup(true); if (target) { target[0].blur(); } }); $("#city_selector").mousedown(function (e) { e.stopPropagation(); e.preventDefault(); }); return this; }; exports.init = function (eleSelector, args) { $("body").append($html); //初始化常用城市 (function () { var html = []; _.each(popcity, function (c) { var city = cityMap[c]; html.push("
  • " + city.n + "
  • "); }); if (popcity.length % 4 !== 0) { for (var i = 0; i < 4 - popcity.length % 4; i++) { html.push("
  • "); } } $("#city_selector .city-pop ul").append(html.join("")); })(); args = $.extend({ rows: 9 }, args); selector = new CitySelector(args); exports.cityui = selector; $(document).on("focus", eleSelector, function () { selector.showPopup($(this)); setTimeout((function() { this.select(); }).bind(this), 1); }).on("blur", eleSelector, function () { selector.hidePopup(); }).on("keydown", eleSelector, function (e) { var code = e.key || e.keyCode; if ((code >= 37 && code <= 40) || code === 13) { e.stopPropagation(); e.preventDefault(); switch (code) { case 37: //< selector.selectNext(-1); break; case 38: //^ selector.selectNext(-4); break; case 39: //> selector.selectNext(); break; case 40: //下 selector.selectNext(4); break; case 13: //选定 selector.selectToTarget(); this.blur(); break; default: } return false; } }).on("keyup", eleSelector, function (e) { var code = e.key || e.keyCode; if ((code >= 65 && code <= 90) || code === 8 || e.ctrlKey) selector.performSearch.call(this); }); } });