395 lines
11 KiB
JavaScript
395 lines
11 KiB
JavaScript
define(function (require, exports) {
|
||
var $html = '<div id="city_selector"><ul class="city-tab-nav"><li class="selected">常用</li><li data-code="A-E">A-E</li><li data-code="F-J">F-J</li><li data-code="K-O">K-O</li><li data-code="P-T">P-T</li><li data-code="U-Z">U-Z</li></ul><div class="recent-city-list"><p>最近查询</p><dl><dd>TEST</dd></dl></div><div class="city-pop"><p>常用城市</p><ul class="city-list-container"></ul></div><div class="city-search"><p>站点列表</p><ul class="city-list-container"></ul><div class="city-list-pager"><button class="city-prev" disabled="disabled">上一页</button><button class="city-next">下一页</button></div></div></div>';
|
||
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}}<dd data-code='{{=c.c}}'>{{!c.n}}</dd>{{~}}");
|
||
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) {
|
||
/// <summary>切换当前的分页</summary>
|
||
|
||
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("<li data-code='" + city.c + "' data-py='" + city.p + "' data-name='" + city.n + "' data-fl='" + city.h + "'>" + city.n + "</li>");
|
||
}
|
||
if (listCount % 4 !== 0) {
|
||
for (var i = 0; i < 4 - listCount % 4; i++) {
|
||
html.push("<li></li>");
|
||
}
|
||
}
|
||
|
||
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("<li data-code='" + city.c + "' data-py='" + city.p + "' data-name='" + city.n + "' data-fl='" + city.h + "'>" + city.n + "</li>");
|
||
});
|
||
|
||
if (popcity.length % 4 !== 0) {
|
||
for (var i = 0; i < 4 - popcity.length % 4; i++) {
|
||
html.push("<li></li>");
|
||
}
|
||
}
|
||
|
||
$("#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);
|
||
});
|
||
}
|
||
}); |