Light12306/Web12306/js/ui/widget_cityselector.js

395 lines
11 KiB
JavaScript
Raw Normal View History

2014-05-16 20:10:45 +08:00
define(function (require, exports) {
2014-07-08 20:11:31 +08:00
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>';
2014-05-05 19:34:47 +08:00
var selector;
2014-07-04 20:57:57 +08:00
var data = require("../data.js");
2014-05-05 19:34:47 +08:00
2014-07-04 20:57:57 +08:00
var cityMap = data.cities;
2014-07-08 20:11:31 +08:00
var citydata = data.citydata.data;
var popcity = data.citydata.popcity;
var maxRecentCity = 8;
var sessMgr = require("../account/sessionMgr.js");
2014-05-16 20:10:45 +08:00
var CitySelector = function (options) {
2014-05-05 19:34:47 +08:00
var that = this;
2014-05-16 20:10:45 +08:00
var dom = $("#city_selector");
var currentList = null;
var currentPage = 1;
var totalPage = 1;
var pageSize = options.rows * 4;
var target = null;
var prevTab = null;
2014-05-27 19:40:21 +08:00
var searchKey;
2014-07-08 20:11:31 +08:00
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]]));
};
2014-05-16 20:10:45 +08:00
2014-05-27 19:40:21 +08:00
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;
};
2014-05-16 20:10:45 +08:00
that.performSearch = function () {
2014-05-27 19:40:21 +08:00
target = $(this);
2014-05-16 20:10:45 +08:00
var key = target.val().replace(/\s/g, "");
2014-05-27 19:40:21 +08:00
if (key === searchKey) return;
searchKey = key;
2014-05-05 19:34:47 +08:00
2014-05-16 20:10:45 +08:00
if (!key) {
that.switchTab(prevTab);
return;
}
2014-05-27 19:40:21 +08:00
2014-05-16 20:10:45 +08:00
//清空选择
that.switchTab();
dom.find(".city-search").show().find(">p").html("搜索“" + key + "”");
//搜索城市
key = key.toUpperCase();
var lkey = key.toLowerCase();
2014-05-27 19:40:21 +08:00
currentList = _.filter(_.values(cityMap), function (e) {
2014-05-16 20:10:45 +08:00
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) {
2014-05-27 19:40:21 +08:00
if (selector.isVisible)
return;
searchKey = null;
2014-05-16 20:10:45 +08:00
that.switchTab(dom.find(".city-tab-nav li:first"));
2014-05-27 19:40:21 +08:00
dom.find(".city-list-container li, dd[data-code]").removeClass("selected");
2014-05-05 19:34:47 +08:00
var offset = ele.offset();
2014-05-27 19:40:21 +08:00
dom.css({ left: offset.left + "px", top: (offset.top + ele.height()) + "px" });
dom.addClass("open");
2014-05-16 20:10:45 +08:00
target = ele;
2014-05-05 19:34:47 +08:00
};
2014-05-27 19:40:21 +08:00
that.hidePopup = function (force) {
2014-07-08 20:11:31 +08:00
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);
2014-06-20 20:55:14 +08:00
}
2014-07-08 20:11:31 +08:00
target[0].dispatchEvent(new UIEvent("change"));
2014-06-20 20:55:14 +08:00
2014-05-27 19:40:21 +08:00
if (force) {
dom.css("top", "-2000px");
2014-05-16 20:10:45 +08:00
}
2014-05-05 19:34:47 +08:00
};
2014-05-16 20:10:45 +08:00
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("站点列表");
2014-07-08 20:11:31 +08:00
currentList = _.values(citydata[code]);
2014-05-16 20:10:45 +08:00
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();
}
2014-05-27 19:40:21 +08:00
dom.find(".city-list-container ul, dd[data-code]").removeClass("selected");
that.currentShownCities = null;
2014-05-16 20:10:45 +08:00
};
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;
2014-05-27 19:40:21 +08:00
that.currentShownCities = null;
2014-05-16 20:10:45 +08:00
};
that.showNextPage = function () {
that.renderPage(currentPage + 1);
};
that.showPrevPage = function () {
that.renderPage(currentPage - 1);
2014-05-27 19:40:21 +08:00
};
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");
2014-06-20 20:55:14 +08:00
var nextSelect = null;
2014-05-27 19:40:21 +08:00
if (!current.length) {
//尚没有选择
if (offset > 0) {
//向下移动,则默认选择第一个
2014-06-20 20:55:14 +08:00
(nextSelect = eles.first()).addClass("selected");
2014-05-27 19:40:21 +08:00
} else {
2014-06-20 20:55:14 +08:00
(nextSelect = eles.last()).addClass("selected");
2014-05-27 19:40:21 +08:00
}
} else {
var index = eles.index(current);
index += offset;
if (index < 0) {
if (currentPage > 1) {
that.showPrevPage();
2014-06-20 20:55:14 +08:00
(nextSelect = dom.find("div.city-search ul.city-list-container li[data-code]:last")).addClass("selected");
2014-05-27 19:40:21 +08:00
}
} else if (index >= eles.length) {
if (currentPage < totalPage) {
that.showNextPage();
2014-06-20 20:55:14 +08:00
(nextSelect = dom.find("div.city-search ul.city-list-container li[data-code]:first")).addClass("selected");
2014-05-27 19:40:21 +08:00
}
} else {
current.removeClass("selected");
2014-06-20 20:55:14 +08:00
nextSelect = eles.eq(index).addClass("selected");
2014-05-27 19:40:21 +08:00
}
}
2014-06-20 20:55:14 +08:00
if (nextSelect) {
that.selectToTarget(nextSelect.attr("data-code"));
}
2014-05-16 20:10:45 +08:00
};
dom.find("button.city-prev").click(that.showPrevPage);
dom.find("button.city-next").click(that.showNextPage);
2014-05-05 19:34:47 +08:00
2014-05-27 19:40:21 +08:00
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);
2014-06-20 20:55:14 +08:00
var ce = new UIEvent("change");
ele[0].dispatchEvent(ce);
2014-05-27 19:40:21 +08:00
};
$(document).on("click", ".recent-city-list dd[data-code], .city-list-container li[data-code]", function () {
//选定城市
that.selectToTarget(this.dataset.code);
that.hidePopup(true);
2014-06-20 20:55:14 +08:00
if (target) {
target[0].blur();
}
});
2014-07-08 20:11:31 +08:00
$("#city_selector").mousedown(function (e) {
e.stopPropagation();
e.preventDefault();
2014-05-27 19:40:21 +08:00
});
2014-05-05 19:34:47 +08:00
return this;
};
2014-05-16 20:10:45 +08:00
exports.init = function (eleSelector, args) {
2014-05-05 19:34:47 +08:00
$("body").append($html);
2014-05-16 20:10:45 +08:00
//初始化常用城市
(function () {
var html = [];
2014-05-05 19:34:47 +08:00
2014-07-08 20:11:31 +08:00
_.each(popcity, function (c) {
2014-05-16 20:10:45 +08:00
var city = cityMap[c];
2014-05-05 19:34:47 +08:00
2014-05-16 20:10:45 +08:00
html.push("<li data-code='" + city.c + "' data-py='" + city.p + "' data-name='" + city.n + "' data-fl='" + city.h + "'>" + city.n + "</li>");
});
2014-07-08 20:11:31 +08:00
if (popcity.length % 4 !== 0) {
for (var i = 0; i < 4 - popcity.length % 4; i++) {
2014-05-16 20:10:45 +08:00
html.push("<li></li>");
}
}
$("#city_selector .city-pop ul").append(html.join(""));
})();
args = $.extend({ rows: 9 }, args);
selector = new CitySelector(args);
2014-07-08 20:11:31 +08:00
exports.cityui = selector;
2014-05-05 19:34:47 +08:00
$(document).on("focus", eleSelector, function () {
selector.showPopup($(this));
2014-07-29 21:19:06 +08:00
setTimeout((function() { this.select(); }).bind(this), 1);
2014-05-05 19:34:47 +08:00
}).on("blur", eleSelector, function () {
2014-05-27 19:40:21 +08:00
selector.hidePopup();
}).on("keydown", eleSelector, function (e) {
var code = e.key || e.keyCode;
2014-05-16 20:10:45 +08:00
2014-05-27 19:40:21 +08:00
if ((code >= 37 && code <= 40) || code === 13) {
e.stopPropagation();
e.preventDefault();
2014-05-16 20:10:45 +08:00
2014-05-27 19:40:21 +08:00
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:
//选定
2014-05-29 19:41:38 +08:00
selector.selectToTarget();
2014-06-20 20:55:14 +08:00
this.blur();
2014-05-27 19:40:21 +08:00
break;
default:
}
return false;
}
2014-06-20 20:55:14 +08:00
}).on("keyup", eleSelector, function (e) {
var code = e.key || e.keyCode;
if ((code >= 65 && code <= 90) || code === 8 || e.ctrlKey)
selector.performSearch.call(this);
});
2014-05-27 19:40:21 +08:00
}
2014-05-05 19:34:47 +08:00
});