CityList.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. /**
  2. * @fileoverview 百度地图的城市列表类,对外开放。
  3. * 帮助用户直接生成城市列表,并自定义点击城市的操作。
  4. * 使用者可以通过接口直接获取城市数据。
  5. * 主入口类是<a href="symbols/BMapLib.CityList.html">CityList</a>,
  6. * 基于Baidu Map API 1.5。
  7. *
  8. * @author Baidu Map Api Group
  9. * @version 1.5
  10. */
  11. /**
  12. * @namespace BMap的所有library类均放在BMapLib命名空间下
  13. */
  14. var BMapLib = window.BMapLib = BMapLib || {};
  15. (function() {
  16. /**
  17. * 声明baidu包
  18. */
  19. var baidu = baidu || {guid : "$BAIDU$"};
  20. (function() {
  21. // 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
  22. window[baidu.guid] = {};
  23. /**
  24. * 将源对象的所有属性拷贝到目标对象中
  25. * @name baidu.extend
  26. * @function
  27. * @grammar baidu.extend(target, source)
  28. * @param {Object} target 目标对象
  29. * @param {Object} source 源对象
  30. * @returns {Object} 目标对象
  31. */
  32. baidu.extend = function (target, source) {
  33. for (var p in source) {
  34. if (source.hasOwnProperty(p)) {
  35. target[p] = source[p];
  36. }
  37. }
  38. return target;
  39. };
  40. /**
  41. * @ignore
  42. * @namespace
  43. * @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
  44. * @property guid 对象的唯一标识
  45. */
  46. baidu.lang = baidu.lang || {};
  47. /**
  48. * 返回一个当前页面的唯一标识字符串。
  49. * @function
  50. * @grammar baidu.lang.guid()
  51. * @returns {String} 当前页面的唯一标识字符串
  52. */
  53. baidu.lang.guid = function() {
  54. return "TANGRAM__" + (window[baidu.guid]._counter ++).toString(36);
  55. };
  56. window[baidu.guid]._counter = window[baidu.guid]._counter || 1;
  57. /**
  58. * 所有类的实例的容器
  59. * key为每个实例的guid
  60. */
  61. window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  62. /**
  63. * Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
  64. * @function
  65. * @name baidu.lang.Class
  66. * @grammar baidu.lang.Class(guid)
  67. * @param {string} guid 对象的唯一标识
  68. * @meta standard
  69. * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。
  70. * guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>
  71. * baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
  72. */
  73. baidu.lang.Class = function(guid) {
  74. this.guid = guid || baidu.lang.guid();
  75. window[baidu.guid]._instances[this.guid] = this;
  76. };
  77. window[baidu.guid]._instances = window[baidu.guid]._instances || {};
  78. /**
  79. * 判断目标参数是否string类型或String对象
  80. * @name baidu.lang.isString
  81. * @function
  82. * @grammar baidu.lang.isString(source)
  83. * @param {Any} source 目标参数
  84. * @shortcut isString
  85. * @meta standard
  86. *
  87. * @returns {boolean} 类型判断结果
  88. */
  89. baidu.lang.isString = function (source) {
  90. return '[object String]' == Object.prototype.toString.call(source);
  91. };
  92. /**
  93. * 判断目标参数是否为function或Function实例
  94. * @name baidu.lang.isFunction
  95. * @function
  96. * @grammar baidu.lang.isFunction(source)
  97. * @param {Any} source 目标参数
  98. * @returns {boolean} 类型判断结果
  99. */
  100. baidu.lang.isFunction = function (source) {
  101. return '[object Function]' == Object.prototype.toString.call(source);
  102. };
  103. /**
  104. * 重载了默认的toString方法,使得返回信息更加准确一些。
  105. * @return {string} 对象的String表示形式
  106. */
  107. baidu.lang.Class.prototype.toString = function(){
  108. return "[object " + (this._className || "Object" ) + "]";
  109. };
  110. /**
  111. * 自定义的事件对象。
  112. * @function
  113. * @name baidu.lang.Event
  114. * @grammar baidu.lang.Event(type[, target])
  115. * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
  116. * @param {Object} [target]触发事件的对象
  117. * @meta standard
  118. * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
  119. * @see baidu.lang.Class
  120. */
  121. baidu.lang.Event = function (type, target) {
  122. this.type = type;
  123. this.returnValue = true;
  124. this.target = target || null;
  125. this.currentTarget = null;
  126. };
  127. /**
  128. * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  129. * @grammar obj.addEventListener(type, handler[, key])
  130. * @param {string} type 自定义事件的名称
  131. * @param {Function} handler 自定义事件被触发时应该调用的回调函数
  132. * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
  133. * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
  134. */
  135. baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
  136. if (!baidu.lang.isFunction(handler)) {
  137. return;
  138. }
  139. !this.__listeners && (this.__listeners = {});
  140. var t = this.__listeners, id;
  141. if (typeof key == "string" && key) {
  142. if (/[^\w\-]/.test(key)) {
  143. throw("nonstandard key:" + key);
  144. } else {
  145. handler.hashCode = key;
  146. id = key;
  147. }
  148. }
  149. type.indexOf("on") != 0 && (type = "on" + type);
  150. typeof t[type] != "object" && (t[type] = {});
  151. id = id || baidu.lang.guid();
  152. handler.hashCode = id;
  153. t[type][id] = handler;
  154. };
  155. /**
  156. * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  157. * @grammar obj.removeEventListener(type, handler)
  158. * @param {string} type 事件类型
  159. * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
  160. * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
  161. */
  162. baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
  163. if (baidu.lang.isFunction(handler)) {
  164. handler = handler.hashCode;
  165. } else if (!baidu.lang.isString(handler)) {
  166. return;
  167. }
  168. !this.__listeners && (this.__listeners = {});
  169. type.indexOf("on") != 0 && (type = "on" + type);
  170. var t = this.__listeners;
  171. if (!t[type]) {
  172. return;
  173. }
  174. t[type][handler] && delete t[type][handler];
  175. };
  176. /**
  177. * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
  178. * @grammar obj.dispatchEvent(event, options)
  179. * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
  180. * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
  181. * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。
  182. * 例如:<br>
  183. * myobj.onMyEvent = function(){}<br>
  184. * myobj.addEventListener("onMyEvent", function(){});
  185. */
  186. baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
  187. if (baidu.lang.isString(event)) {
  188. event = new baidu.lang.Event(event);
  189. }
  190. !this.__listeners && (this.__listeners = {});
  191. options = options || {};
  192. for (var i in options) {
  193. event[i] = options[i];
  194. }
  195. var i, t = this.__listeners, p = event.type;
  196. event.target = event.target || this;
  197. event.currentTarget = this;
  198. p.indexOf("on") != 0 && (p = "on" + p);
  199. baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
  200. if (typeof t[p] == "object") {
  201. for (i in t[p]) {
  202. t[p][i].apply(this, arguments);
  203. }
  204. }
  205. return event.returnValue;
  206. };
  207. /**
  208. * 为类型构造器建立继承关系
  209. * @name baidu.lang.inherits
  210. * @function
  211. * @grammar baidu.lang.inherits(subClass, superClass[, className])
  212. * @param {Function} subClass 子类构造器
  213. * @param {Function} superClass 父类构造器
  214. * @param {string} className 类名标识
  215. * @remark 使subClass继承superClass的prototype,
  216. * 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。<br>
  217. * 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。<br>
  218. * <strong>注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子</strong>
  219. * @shortcut inherits
  220. * @meta standard
  221. * @see baidu.lang.Class
  222. */
  223. baidu.lang.inherits = function (subClass, superClass, className) {
  224. var key, proto,
  225. selfProps = subClass.prototype,
  226. clazz = new Function();
  227. clazz.prototype = superClass.prototype;
  228. proto = subClass.prototype = new clazz();
  229. for (key in selfProps) {
  230. proto[key] = selfProps[key];
  231. }
  232. subClass.prototype.constructor = subClass;
  233. subClass.superClass = superClass.prototype;
  234. if ("string" == typeof className) {
  235. proto._className = className;
  236. }
  237. };
  238. /**
  239. * @ignore
  240. * @namespace baidu.dom 操作dom的方法。
  241. */
  242. baidu.dom = baidu.dom || {};
  243. /**
  244. * 从文档中获取指定的DOM元素
  245. * @name baidu.dom.g
  246. * @function
  247. * @grammar baidu.dom.g(id)
  248. * @param {string|HTMLElement} id 元素的id或DOM元素
  249. * @meta standard
  250. *
  251. * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
  252. */
  253. baidu.g = baidu.dom.g = function (id) {
  254. if ('string' == typeof id || id instanceof String) {
  255. return document.getElementById(id);
  256. } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
  257. return id;
  258. }
  259. return null;
  260. };
  261. /**
  262. * @ignore
  263. * @namespace baidu.browser 判断浏览器类型和特性的属性。
  264. */
  265. baidu.browser = baidu.browser || {};
  266. if (/msie (\d+\.\d)/i.test(navigator.userAgent)) {
  267. //IE 8下,以documentMode为准
  268. /**
  269. * 判断是否为ie浏览器
  270. * @property ie ie版本号
  271. * @grammar baidu.browser.ie
  272. * @meta standard
  273. * @shortcut ie
  274. * @see baidu.browser.firefox,baidu.browser.safari,baidu.browser.opera,baidu.browser.chrome,baidu.browser.maxthon
  275. */
  276. baidu.browser.ie = baidu.ie = document.documentMode || + RegExp['\x241'];
  277. }
  278. /**
  279. * 提供给setAttr与getAttr方法作名称转换使用
  280. * ie6,7下class要转换成className
  281. * @meta standard
  282. */
  283. baidu.dom._NAME_ATTRS = (function () {
  284. var result = {
  285. 'cellpadding': 'cellPadding',
  286. 'cellspacing': 'cellSpacing',
  287. 'colspan': 'colSpan',
  288. 'rowspan': 'rowSpan',
  289. 'valign': 'vAlign',
  290. 'usemap': 'useMap',
  291. 'frameborder': 'frameBorder'
  292. };
  293. if (baidu.browser.ie < 8) {
  294. result['for'] = 'htmlFor';
  295. result['class'] = 'className';
  296. } else {
  297. result['htmlFor'] = 'for';
  298. result['className'] = 'class';
  299. }
  300. return result;
  301. })();
  302. /**
  303. * 获取目标元素的属性值
  304. * @name baidu.dom.getAttr
  305. * @function
  306. * @grammar baidu.dom.getAttr(element, key)
  307. * @param {HTMLElement|string} element 目标元素或目标元素的id
  308. * @param {string} key 要获取的attribute键名
  309. * @shortcut getAttr
  310. * @meta standard
  311. * @see baidu.dom.setAttr,baidu.dom.setAttrs
  312. *
  313. * @returns {string|null} 目标元素的attribute值,获取不到时返回null
  314. */
  315. baidu.getAttr = baidu.dom.getAttr = function (element, key) {
  316. element = baidu.dom.g(element);
  317. if ('style' == key){
  318. return element.style.cssText;
  319. }
  320. key = baidu.dom._NAME_ATTRS[key] || key;
  321. return element.getAttribute(key);
  322. };
  323. /**
  324. * @ignore
  325. * @namespace baidu.event 屏蔽浏览器差异性的事件封装。
  326. * @property target 事件的触发元素
  327. * @property pageX 鼠标事件的鼠标x坐标
  328. * @property pageY 鼠标事件的鼠标y坐标
  329. * @property keyCode 键盘事件的键值
  330. */
  331. baidu.event = baidu.event || {};
  332. /**
  333. * 事件监听器的存储表
  334. * @private
  335. * @meta standard
  336. */
  337. baidu.event._listeners = baidu.event._listeners || [];
  338. /**
  339. * 为目标元素添加事件监听器
  340. * @name baidu.event.on
  341. * @function
  342. * @grammar baidu.event.on(element, type, listener)
  343. * @param {HTMLElement|string|window} element 目标元素或目标元素id
  344. * @param {string} type 事件类型
  345. * @param {Function} listener 需要添加的监听器
  346. * @remark
  347. * 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
  348. * 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
  349. * @shortcut on
  350. * @meta standard
  351. * @see baidu.event.un
  352. *
  353. * @returns {HTMLElement|window} 目标元素
  354. */
  355. baidu.on = baidu.event.on = function (element, type, listener) {
  356. type = type.replace(/^on/i, '');
  357. element = baidu.g(element);
  358. var realListener = function (ev) {
  359. // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
  360. // 2. element是为了修正this
  361. listener.call(element, ev);
  362. },
  363. lis = baidu.event._listeners,
  364. filter = baidu.event._eventFilter,
  365. afterFilter,
  366. realType = type;
  367. type = type.toLowerCase();
  368. // filter过滤
  369. if(filter && filter[type]){
  370. afterFilter = filter[type](element, type, realListener);
  371. realType = afterFilter.type;
  372. realListener = afterFilter.listener;
  373. }
  374. // 事件监听器挂载
  375. if (element.addEventListener) {
  376. element.addEventListener(realType, realListener, false);
  377. } else if (element.attachEvent) {
  378. element.attachEvent('on' + realType, realListener);
  379. }
  380. // 将监听器存储到数组中
  381. lis[lis.length] = [element, type, listener, realListener, realType];
  382. return element;
  383. };
  384. })();
  385. /**
  386. * @fileoverview 数据管理模块.
  387. */
  388. var DataMgr = {
  389. /**
  390. * 请求函数
  391. * @param String 地址.
  392. * @param Function 回调函数.
  393. */
  394. request: function(url, cbk) {
  395. if (cbk) {
  396. // 生成随机数
  397. var timeStamp = (Math.random() * 100000).toFixed(0);
  398. // 全局回调函数
  399. BMap["_rd"]["_cbk" + timeStamp] = function(json){
  400. cbk && cbk(json);
  401. delete BMap["_rd"]["_cbk" + timeStamp];
  402. };
  403. url += "&callback=BMap._rd._cbk" + timeStamp;
  404. }
  405. var script = document.createElement('script');
  406. script.setAttribute('src', url);
  407. document.body.appendChild(script);
  408. // 脚本加载完成后进行移除
  409. if (script.addEventListener) {
  410. script.addEventListener('load', function(e) {
  411. var t = e.target;
  412. t.parentNode.removeChild(t);
  413. }, false);
  414. }
  415. else if (script.attachEvent) {
  416. script.attachEvent('onreadystatechange', function(e) {
  417. var t = window.event.srcElement;
  418. if (t && (t.readyState == 'loaded' || t.readyState == 'complete')) {
  419. t.parentNode.removeChild(t);
  420. }
  421. });
  422. }
  423. // 使用setTimeout解决ie6无法发送问题
  424. setTimeout(function() {
  425. document.getElementsByTagName('head')[0].appendChild(script);
  426. script = null;
  427. }, 1);
  428. }
  429. };
  430. var config = {
  431. serviceUrl : "http://api.map.baidu.com"
  432. }
  433. function geoToPoint(geo) {
  434. var projection = BMAP_NORMAL_MAP.getProjection();
  435. var point = null;
  436. geo = geo.split('|')[2];
  437. geo = geo.substr(0, geo.length - 1);
  438. geo = geo.split(',');
  439. var point = projection.pointToLngLat(new BMap.Pixel(geo[0], geo[1]));
  440. return point;
  441. }
  442. function coordinateToPoints(coordinate) {
  443. var projection = BMAP_NORMAL_MAP.getProjection();
  444. var points = [];
  445. coordinate = coordinate.split(';');
  446. for (var i = 0, len = coordinate.length; i < len; i++) {
  447. var pos = coordinate[i].split(',');
  448. var point = projection.pointToLngLat(new BMap.Pixel(pos[0], pos[1]));
  449. points.push(point);
  450. }
  451. return points;
  452. }
  453. /**
  454. * @exports CityList as BMapLib.CityList
  455. */
  456. var CityList =
  457. /**
  458. * CityList类的构造函数
  459. * @class 城市列表类,
  460. * 实例化该类后,可以帮助用户直接生成城市列表,
  461. * 也可以通过接口获取城市数据。
  462. *
  463. * @constructor
  464. * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
  465. * {"<b>container</b>" : {String|HTMLElement} 需要提供界面方式展现的容器。如果此参数为空,则不提供界面方式,也没有cityclick的事件派发
  466. * <br />"<b>map</b>" : {BMap} 实例化的map对象,如果传入此参数,则用户点击界面中的城市时,可以直接帮助用户定位到地图的相关城市位置}
  467. *
  468. * @example <b>参考示例:</b><br />
  469. * var myCityListObject = new BMapLib.CityList({container : "container"});
  470. */
  471. BMapLib.CityList = function(opts){
  472. opts = opts || {};
  473. /**
  474. * _opts是默认参数赋值。
  475. * 下面通过用户输入的opts,对默认参数赋值
  476. * @private
  477. * @type {Json}
  478. */
  479. this._opts = baidu.extend(
  480. baidu.extend(this._opts || {}, {
  481. /**
  482. * 提供界面方式展现的容器
  483. * @private
  484. * @type {String|HTMLElement}
  485. */
  486. container : null,
  487. /**
  488. * 实例化的BMap对象
  489. * @private
  490. * @type {BMap}
  491. */
  492. map : null
  493. })
  494. , opts);
  495. /**
  496. * 城市数据的存储
  497. * @private
  498. * @type {Json}
  499. */
  500. this._data = null;
  501. this._init();
  502. }
  503. // 通过baidu.lang下的inherits方法,让CityList继承baidu.lang.Class
  504. baidu.lang.inherits(CityList, baidu.lang.Class, "CityList");
  505. CityList.prototype._init = function () {
  506. //if (this._opts.container && !$('#'+this._opts.container).html()){
  507. this._initContainer();
  508. //}
  509. }
  510. /**
  511. * 获取商圈数据
  512. * @param {String} 商圈名称
  513. * @param {Function} 回调函数,结果在回调函数中回传
  514. * [<br/>
  515. * {<br/>
  516. * city: "北京市", //商圈所在城市名<br/>
  517. * coordinate: {Array}, //商圈所在的坐标范围,Point数组<br/>
  518. * district: "海淀区", //商圈所在的区域<br/>
  519. * type: "4-优质商圈" //商圈的类型<br/>
  520. * }<br/>
  521. * ]<br/>
  522. *
  523. */
  524. CityList.prototype.getBusiness = function (business, cbk) {
  525. var url = config.serviceUrl + "/shangquan/reverse/?wd=" + business;
  526. DataMgr.request(url,function(json){
  527. var result = null;
  528. if (json && json['error'] && json['error']['errno'] == "0") {
  529. result = json['content'];
  530. }
  531. for (var i = 0, len = result.length; i < len; i++) {
  532. result[i]['coordinate'] = coordinateToPoints(result[i]['coordinate']);
  533. }
  534. console.log(result);
  535. if (cbk) {
  536. cbk(result);
  537. }
  538. });
  539. }
  540. /**
  541. * 获取下级的区域列表
  542. * @param {String} 城市代码(cityCode),参考百度地图城市名称-城市代码(cityCode)关系对照:http://developer.baidu.com/map/devRes.htm
  543. * @param {Function} 回调函数,结果在回调函数中回传<br/>
  544. * 返回的json结果代表的意思<br/>
  545. * {<br/>
  546. * area_code: 131, //城市区域code<br/>
  547. * area_name: "北京市", //城市区域名称<br/>
  548. * area_type: 2, //城市区域类型<br/>
  549. * geo: {Point}, //城市区域中心点<br/>
  550. * sup_business_area: 0 ,//是否存在商圈,仅在区的级别(area_type=3)才会有此字段<br/>
  551. * sub: {Array} //下级区域列表, 里面内容同上面的那些字段<br/>
  552. * }<br/>
  553. */
  554. CityList.prototype.getSubAreaList = function (areaCode, cbk) {
  555. var url = config.serviceUrl + "/shangquan/forward/?qt=sub_area_list&ext=1&level=1&areacode=" + areaCode + "&business_flag=0";
  556. DataMgr.request(url,function(json){
  557. var result = null;
  558. if (json && json['result'] && json['result']['error'] == "0") {
  559. result = json['content'];
  560. }
  561. result.geo = geoToPoint(result.geo);
  562. for (var i = 0, len = result.sub.length; i < len; i++) {
  563. result.sub[i]['geo'] = geoToPoint(result.sub[i]['geo']);
  564. }
  565. console.log(result);
  566. if (cbk) {
  567. cbk(result);
  568. }
  569. });
  570. }
  571. CityList.prototype._initContainer = function () {
  572. var me = this;
  573. /*请城市地区*/
  574. function selectArea(areacode, id, level, isbusiness){
  575. selectArea.id = id;
  576. selectArea.level = level;
  577. var t= new Date().getTime();
  578. var url = AreaUrl + "&areacode=" + areacode;
  579. if (isbusiness) {
  580. url += "&business_flag=1";
  581. } else {
  582. url += "&business_flag=0";
  583. }
  584. DataMgr.request(url,getAreaData);
  585. }
  586. function getAreaData(data){
  587. var subList = "";//城区列表
  588. if(data.content){
  589. var c = data.content;
  590. var html = [];
  591. var geo = execGeo(c.geo);
  592. var mp = new BMap.MercatorProjection();
  593. var po = mp.pointToLngLat(new BMap.Pixel(geo.x, geo.y))
  594. if(data.content.area_code == 1){
  595. var point = new BMap.Point(121.455129,31.229402);
  596. map.centerAndZoom(point, 12);
  597. }else{
  598. var point = new BMap.Point(po.lng, po.lat);
  599. map.centerAndZoom(point, selectArea.level);
  600. }
  601. /*渲染城市*/
  602. if(data.content.sub){
  603. subList = c.sub;
  604. subList.splice(0,0,{area_name:'请选择', area_code:''});
  605. var fragment = document.createDocumentFragment();
  606. var o;
  607. var citycode = {131: 1, 289: 2, 332: 3, 132: 4};
  608. for(var i=0; i<subList.length;i++){
  609. subList[i].sort = subList[i].area_code ? citycode[subList[i].area_code] || 5 : 0 ;
  610. }
  611. subList.sort(function(a, b){
  612. return a.sort - b.sort;
  613. });
  614. for(var i=0; i<subList.length;i++){
  615. o = document.createElement("option");
  616. o.innerHTML = subList[i].area_name;
  617. o.area_type = subList[i].area_type;
  618. o.geo = subList[i].geo;
  619. if (subList[i].business_geo) {
  620. o.business_geo = subList[i].business_geo;
  621. }
  622. o.value = subList[i].area_code;
  623. o.title = subList[i].area_name;
  624. fragment.appendChild(o);
  625. }
  626. subList.shift();
  627. if(selectArea.id){
  628. selectArea.id.innerHTML = '';
  629. selectArea.id.appendChild(fragment);
  630. }
  631. }
  632. }
  633. }
  634. function execGeo(str){
  635. var reg = /([^\|;]*)(?=;)/;
  636. var myStr = reg.exec(str);
  637. var myArr_x = myStr[0].split(",")[0]*1
  638. var myArr_y = myStr[0].split(",")[1]*1
  639. var geo = {"x":myArr_x,"y":myArr_y}
  640. return geo;
  641. }
  642. var AreaUrl = config.serviceUrl + "/shangquan/forward/?qt=sub_area_list&ext=1&level=1"
  643. $('#'+this._opts.container).html('');
  644. var cssText = "width:70px;margin:0 5px;";
  645. var container = baidu.g(this._opts.container),
  646. provinceDom = document.createElement('select'),
  647. cityDom = document.createElement('select'),
  648. boroughDom = document.createElement('select'),
  649. businessDom = document.createElement('select');
  650. provinceDom.style.cssText = cssText;
  651. cityDom.style.cssText = cssText;
  652. boroughDom.style.cssText = cssText;
  653. businessDom.style.cssText = cssText;
  654. //provinceDom.id = '';
  655. //cityDom.id = '';
  656. //boroughDom.id = '';
  657. container.appendChild(provinceDom);
  658. container.appendChild(document.createTextNode('省'));
  659. container.appendChild(cityDom);
  660. container.appendChild(document.createTextNode('市'));
  661. container.appendChild(boroughDom);
  662. container.appendChild(document.createTextNode('区'));
  663. container.appendChild(businessDom);
  664. container.appendChild(document.createTextNode('商圈'));
  665. /*第一步 表单操作*/
  666. baidu.on(provinceDom, "change", function(){
  667. //localStorage.province=provinceDom.options[provinceDom.selectedIndex].text;//省
  668. storage.removeItem('province');
  669. storage.removeItem('city');
  670. storage.removeItem('area');
  671. storage.removeItem('business');
  672. storage.removeItem('points');
  673. storage.setItem('province',provinceDom.options[provinceDom.selectedIndex].text);
  674. var s_value = provinceDom.value;
  675. cityDom.innerHTML = boroughDom.innerHTML = businessDom.innerHTML = "";
  676. if( s_value == 131 || s_value == 289 || s_value == 332 || s_value == 132){
  677. var cityName = ""
  678. switch(s_value){
  679. case "131" : cityName = "北京市";
  680. break;
  681. case "289" : cityName = "上海市";
  682. break;
  683. case "332" : cityName = "天津市";
  684. break;
  685. case "132" : cityName = "重庆市";
  686. break;
  687. }
  688. var fragment = document.createDocumentFragment();
  689. var o;
  690. o = document.createElement("option");
  691. o.innerHTML = cityName;
  692. o.value = s_value;
  693. o.title = cityName;
  694. fragment.appendChild(o);
  695. cityDom.appendChild(fragment)
  696. selectArea(s_value, boroughDom, 12);
  697. storage.removeItem('city');
  698. storage.removeItem('area');
  699. storage.removeItem('business');
  700. storage.removeItem('points');
  701. //localStorage.city=localStorage.province;//市
  702. storage.setItem('city',storage.getItem('province'));
  703. }else{
  704. selectArea(s_value, cityDom, 12);
  705. }
  706. dispatchCityClick(this.options[this.selectedIndex]);
  707. });
  708. baidu.on(cityDom, "change", function(){
  709. //localStorage.city=cityDom.options[cityDom.selectedIndex].text;//市
  710. storage.removeItem('city');
  711. storage.removeItem('area');
  712. storage.removeItem('business');
  713. storage.removeItem('points');
  714. storage.setItem('city',cityDom.options[cityDom.selectedIndex].text);
  715. var s_value = cityDom.value;
  716. selectArea(s_value, boroughDom, 12);
  717. boroughDom.innerHTML = "";
  718. dispatchCityClick(this.options[this.selectedIndex]);
  719. });
  720. baidu.on(boroughDom, "change", function(){
  721. storage.removeItem('area');
  722. storage.removeItem('business');
  723. storage.removeItem('points');
  724. storage.setItem('area',boroughDom.options[boroughDom.selectedIndex].text);
  725. var s_value = boroughDom.value;
  726. var bdary = new BMap.Boundary();
  727. bdary.get(boroughDom.selectedOptions[0].innerText, function(rs){ //获取行政区域
  728. map.clearOverlays(); //清除地图覆盖物
  729. var count = rs.boundaries.length; //行政区域的点有多少个
  730. for(var i = 0; i < count; i++){
  731. var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物
  732. map.addOverlay(ply); //添加覆盖物
  733. map.setViewport(ply.getPath()); //调整视野
  734. }
  735. });
  736. selectArea(s_value, businessDom, 12, 1);
  737. businessDom.innerHTML = "";
  738. dispatchCityClick(this.options[this.selectedIndex]);
  739. });
  740. function dispatchCityClick(option){
  741. /**
  742. * 点击城市名时,派发事件的接口
  743. * @name CityList#oncityclick
  744. * @event
  745. * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
  746. * <br />{"<b>area_name</b> : {String} 点击的区域名称,
  747. * <br />{"<b>area_code</b> : {String} 点击的区域代码,
  748. * <br />"<b>geo</b>:{BMap.Point} 点击区域合适显示的中心点位置,
  749. * <br />"<b>area_type</b>:{Number} 该区域的类型(全国0、省1、城市2)
  750. *
  751. * @example <b>参考示例:</b><br />
  752. * myCityListObject.addEventListener("cityclick", function(e) { alert(e.area_name); });
  753. */
  754. me.dispatchEvent('cityclick', {
  755. area_code: option.value,
  756. area_type: option.area_type,
  757. geo: geoToPoint(option.geo),
  758. area_name: option.title
  759. });
  760. }
  761. baidu.on(businessDom, "change", function(e){
  762. storage.removeItem('business');
  763. storage.removeItem('points');
  764. //localStorage.business=businessDom.options[businessDom.selectedIndex].text;//商圈
  765. storage.setItem('business',businessDom.options[businessDom.selectedIndex].text);
  766. var s_value = businessDom.value;
  767. var option = this.options[this.selectedIndex];
  768. var geo = execGeo(option.geo);
  769. var mp = new BMap.MercatorProjection();
  770. var po = mp.pointToLngLat(new BMap.Pixel(geo.x, geo.y));
  771. var business_geo = option.business_geo;
  772. business_geo = business_geo.split(';');
  773. for (var i = 0,len = business_geo.length; i < len; i++) {
  774. var business_p = business_geo[i].split(',');
  775. business_geo[i] = mp.pointToLngLat(new BMap.Pixel(business_p[0], business_p[1]))
  776. }
  777. var points=new Array();
  778. for (i in business_geo){
  779. points[i] = [business_geo[i].lng,business_geo[i].lat];
  780. }
  781. storage.setItem('points',points);//商圈
  782. map.clearOverlays();
  783. var polygon = new BMap.Polygon();
  784. map.addOverlay(polygon);
  785. polygon.show();
  786. polygon.setPath(business_geo);
  787. map.setViewport(business_geo);
  788. dispatchCityClick(this.options[this.selectedIndex]);
  789. //var point = new BMap.Point(po.lng, po.lat);
  790. //map.centerAndZoom(point, 14);
  791. });
  792. selectArea(1, provinceDom, 12);
  793. }
  794. })();