四級地址插件升級改造(京東商城地址選擇插件)city-picker

来源:https://www.cnblogs.com/jimoer/archive/2018/03/04/8506491.html
-Advertisement-
Play Games

最近公司做的項目要和京東的數據做對接,所以要做個類似京東商品的詳情頁。頁面的數據,是可以從京東介面獲取到的,但是地址插件選擇的效果需要自己實現。前端的同事在之前的項目中,已經選擇了一款地址插件(city-picker.js),但是這款插件最多只支持三級地址,而且最主要的是這插件的地址數據來源,是寫死 ...


最近公司做的項目要和京東的數據做對接,所以要做個類似京東商品的詳情頁。頁面的數據,是可以從京東介面獲取到的,但是地址插件選擇的效果需要自己實現。前端的同事在之前的項目中,已經選擇了一款地址插件(city-picker.js),但是這款插件最多只支持三級地址,而且最主要的是這插件的地址數據來源,是寫死在一個json文件中的,意思就是說,在使用這個插件的時候頁面要一次性的把所有的地址數據都載入出來,這在pc端一般倒還可以承受,但是到了,移動端,隨便一個手機就會卡死,瀏覽器直接崩潰。

經過在網上的各種查找,和研究,發現一個博客,http://www.cnblogs.com/huangchanghuan/p/6681510.html

對city-picker這個插件進行了擴展,擴展成了支持四級地址的插件了。這正是我想要的,因為京東給過來的地址數據就是4級的。正好可以使用。然後就拿過來直接用了。

很強大,完美的滿足了,我的需求。但是這個大神的博客只是將三級地址改造成了四級地址,沒有解決,動態載入數據的問題,就是說用這個四級地址插件的時候,還是要把京東的地址庫數據轉成json文件一次性載入到頁面。這樣的話在移動端瀏覽時還是會把瀏覽器搞崩。

好了,說了這麼多鋪墊的廢話,就是為了引出,我對這個四級地址插件的改造。

直接代碼

  1 /*!
  2  * CityPicker v@VERSION
  3  * https://github.com/tshi0912/citypicker
  4  *
  5  * Copyright (c) 2015-@YEAR Tao Shi
  6  * Released under the MIT license
  7  *
  8  * Date: @DATE
  9  */
 10 
 11 
 12 ChineseDistricts={
 13     "86": {
 14         "中國": [
 15             {
 16                 "address": "北京",
 17                 "code": "1"
 18             },
 19             {
 20                 "address": "上海",
 21                 "code": "2"
 22             },
 23             {
 24                 "address": "天津",
 25                 "code": "3"
 26             },
 27             {
 28                 "address": "重慶",
 29                 "code": "4"
 30             },
 31             {
 32                 "address": "河北",
 33                 "code": "5"
 34             },
 35             {
 36                 "address": "山西",
 37                 "code": "6"
 38             },
 39             {
 40                 "address": "河南",
 41                 "code": "7"
 42             },
 43             {
 44                 "address": "遼寧",
 45                 "code": "8"
 46             },
 47             {
 48                 "address": "吉林",
 49                 "code": "9"
 50             },
 51             {
 52                 "address": "黑龍江",
 53                 "code": "10"
 54             },
 55             {
 56                 "address": "內蒙古",
 57                 "code": "11"
 58             },
 59             {
 60                 "address": "江蘇",
 61                 "code": "12"
 62             },
 63             {
 64                 "address": "山東",
 65                 "code": "13"
 66             },
 67             {
 68                 "address": "安徽",
 69                 "code": "14"
 70             },
 71             {
 72                 "address": "浙江",
 73                 "code": "15"
 74             },
 75             {
 76                 "address": "福建",
 77                 "code": "16"
 78             },
 79             {
 80                 "address": "湖北",
 81                 "code": "17"
 82             },
 83             {
 84                 "address": "湖南",
 85                 "code": "18"
 86             },
 87             {
 88                 "address": "廣東",
 89                 "code": "19"
 90             },
 91             {
 92                 "address": "廣西",
 93                 "code": "20"
 94             },
 95             {
 96                 "address": "江西",
 97                 "code": "21"
 98             },
 99             {
100                 "address": "四川",
101                 "code": "22"
102             },
103             {
104                 "address": "海南",
105                 "code": "23"
106             },
107             {
108                 "address": "貴州",
109                 "code": "24"
110             },
111             {
112                 "address": "雲南",
113                 "code": "25"
114             },
115             {
116                 "address": "西藏",
117                 "code": "26"
118             },
119             {
120                 "address": "陝西",
121                 "code": "27"
122             },
123             {
124                 "address": "甘肅",
125                 "code": "28"
126             },
127             {
128                 "address": "青海",
129                 "code": "29"
130             },
131             {
132                 "address": "寧夏",
133                 "code": "30"
134             },
135             {
136                 "address": "新疆",
137                 "code": "31"
138             },
139             {
140                 "address": "臺灣",
141                 "code": "32"
142             },
143             {
144                 "address": "釣魚島",
145                 "code": "84"
146             },
147             {
148                 "address": "港澳",
149                 "code": "52993"
150             }
151         ]
152     }
153 };
154 
155 (function (factory) {
156     if (typeof define === 'function' && define.amd) {
157         // AMD. Register as anonymous module.
158         define(['jquery', 'ChineseDistricts'], factory);
159     } else if (typeof exports === 'object') {
160         // Node / CommonJS
161         factory(require('jquery'), require('ChineseDistricts'));
162     } else {
163         // Browser globals.
164         factory(jQuery, ChineseDistricts);
165     }
166 })(function ($, ChineseDistricts) {
167 
168     'use strict';
169     if (typeof ChineseDistricts === 'undefined') {
170         throw new Error('The file "city-picker.data.js" must be included first!');
171     }
172     var NAMESPACE = 'citypicker';
173     var EVENT_CHANGE = 'change.' + NAMESPACE;
174     var PROVINCE = 'province';
175     var CITY = 'city';
176     var DISTRICT = 'district';
177     var COUNTY = 'county';
178 
179     function CityPicker(element, options) {
180         this.$element = $(element);
181         this.$dropdown = null;
182         this.options = $.extend({}, CityPicker.DEFAULTS, $.isPlainObject(options) && options);
183         this.active = false;
184         this.dems = [];
185         this.needBlur = false;
186         this.init();
187     }
188 
189     CityPicker.prototype = {
190         constructor: CityPicker,
191 
192         init: function () {
193 
194             this.defineDems();
195 
196             this.render();
197 
198             this.bind();
199 
200             this.active = true;
201         },
202         //界面顯示處理
203         render: function () {
204             var p = this.getPosition(),
205                 placeholder = this.$element.attr('placeholder') || this.options.placeholder,
206                 textspan = '<span class="city-picker-span" style="' +
207                     this.getWidthStyle(p.width) + 'height:' +
208                     p.height + 'px;line-height:' + (p.height - 1) + 'px;">' +
209                     (placeholder ? '<span class="placeholder">' + placeholder + '</span>' : '') +
210                     '<span class="title"></span><div class="arrow"></div>' + '</span>',
211 
212                 dropdown = '<div class="city-picker-dropdown" style="left:0px;top:100%;' +
213                     this.getWidthStyle(p.width, true) + '">' +
214                     '<div class="city-select-wrap">' +
215                     '<div class="city-select-tab">' +
216                     '<a class="active" data-count="province">省份</a>' +
217                     (this.includeDem('city') ? '<a data-count="city">城市</a>' : '') +
218                     (this.includeDem('district') ? '<a data-count="district">區縣</a>' : '') +
219                     (this.includeDem('county') ? '<a data-count="county">鄉鎮</a>' : '') +
220                     '</div>' +
221                     '<div class="city-select-content">' +
222                     '<div class="city-select province" data-count="province"></div>' +
223                     (this.includeDem('city') ? '<div class="city-select city" data-count="city"></div>' : '') +
224                     (this.includeDem('district') ? '<div class="city-select district" data-count="district"></div>' : '') +
225                     (this.includeDem('county') ? '<div class="city-select county" data-count="county"></div>' : '') +
226                     '</div></div>';
227 
228             this.$element.addClass('city-picker-input');
229             this.$textspan = $(textspan).insertAfter(this.$element);
230             this.$dropdown = $(dropdown).insertAfter(this.$textspan);
231             var $select = this.$dropdown.find('.city-select');
232 
233             // setup this.$province, this.$city and/or this.$district object
234             $.each(this.dems, $.proxy(function (i, type) {
235                 this['$' + type] = $select.filter('.' + type + '');
236             }, this));
237 
238             this.refresh();
239         },
240 
241         refresh: function (force) {
242             // clean the data-item for each $select
243             var $select = this.$dropdown.find('.city-select');
244             $select.data('item', null);
245             // parse value from value of the target $element
246             var val = this.$element.val() || '';
247             val = val.split('/');
248             $.each(this.dems, $.proxy(function (i, type) {//遍歷dems
249                 if (val[i] && i < val.length) {
250                     this.options[type] = val[i];//把當前顯示值賦值給options
251                 } else if (force) {
252                     this.options[type] = '';
253                 }
254                 this.output(type);//輸出下拉框顯示數據
255             }, this));
256             this.tab(PROVINCE);
257             this.feedText();//界面顯示選擇的內容
258             this.feedVal();//input標簽value賦值
259         },
260         //dems賦值
261         defineDems: function () {
262             var stop = false;
263             $.each([PROVINCE, CITY, DISTRICT,COUNTY], $.proxy(function (i, type) {
264                 if (!stop) {
265                     this.dems.push(type);
266                 }
267                 if (type === this.options.level) {
268                     stop = true;
269                 }
270             }, this));
271         },
272 
273         includeDem: function (type) {
274             return $.inArray(type, this.dems) !== -1;
275         },
276 
277         getPosition: function () {
278             var p, h, w, s, pw;
279             p = this.$element.position();
280             s = this.getSize(this.$element);
281             h = s.height;
282             w = s.width;
283             if (this.options.responsive) {
284                 pw = this.$element.offsetParent().width();
285                 if (pw) {
286                     w = w / pw;
287                     if (w > 0.99) {
288                         w = 1;
289                     }
290                     w = w * 100 + '%';
291                 }
292             }
293 
294             return {
295                 top: p.top || 0,
296                 left: p.left || 0,
297                 height: h,
298                 width: w
299             };
300         },
301 
302         getSize: function ($dom) {
303             var $wrap, $clone, sizes;
304             if (!$dom.is(':visible')) {
305                 $wrap = $("<div />").appendTo($("body"));
306                 $wrap.css({
307                     "position": "absolute !important",
308                     "visibility": "hidden !important",
309                     "display": "block !important"
310                 });
311 
312                 $clone = $dom.clone().appendTo($wrap);
313 
314                 sizes = {
315                     width: $clone.outerWidth(),
316                     height: $clone.outerHeight()
317                 };
318 
319                 $wrap.remove();
320             } else {
321                 sizes = {
322                     width: $dom.outerWidth(),
323                     height: $dom.outerHeight()
324                 };
325             }
326 
327             return sizes;
328         },
329 
330         getWidthStyle: function (w, dropdown) {
331             if (this.options.responsive && !$.isNumeric(w)) {
332                 return 'width:' + w + ';';
333             } else {
334                 return 'width:' + (dropdown ? Math.max(320, w) : w) + 'px;';
335             }
336         },
337         //綁定事件
338         bind: function () {
339             var $this = this;
340             $(document).on('click', (this._mouteclick = function (e) {
341                 var $target = $(e.target);
342                 var $dropdown, $span, $input;
343                 if ($target.is('.city-picker-span')) {
344                     $span = $target;
345                 } else if ($target.is('.city-picker-span *')) {
346                     $span = $target.parents('.city-picker-span');
347                 }
348                 if ($target.is('.city-picker-input')) {
349                     $input = $target;
350                 }
351                 if ($target.is('.city-picker-dropdown')) {
352                     $dropdown = $target;
353                 } else if ($target.is('.city-picker-dropdown *')) {
354                     $dropdown = $target.parents('.city-picker-dropdown');
355                 }
356                 if ((!$input && !$span && !$dropdown) ||
357                     ($span && $span.get(0) !== $this.$textspan.get(0)) ||
358                     ($input && $input.get(0) !== $this.$element.get(0)) ||
359                     ($dropdown && $dropdown.get(0) !== $this.$dropdown.get(0))) {
360                     $this.close(true);
361                 }
362             }));
363             this.$element.on('change', (this._changeElement = $.proxy(function () {
364                 this.close(true);
365                 this.refresh(true);
366             }, this))).on('focus', (this._focusElement = $.proxy(function () {
367                 this.needBlur = true;
368                 this.open();
369             }, this))).on('blur', (this._blurElement = $.proxy(function () {
370                 if (this.needBlur) {
371                     this.needBlur = false;
372                     this.close(true);
373                 }
374             }, this)));
375             this.$textspan.on('click', function (e) {
376                 var $target = $(e.target), type;
377                 $this.needBlur = false;
378                 if ($target.is('.select-item')) {
379                     type = $target.data('count');
380                     $this.open(type);
381                 } else {
382                     if ($this.$dropdown.is(':visible')) {
383                         $this.close();
384                     } else {
385                         $this.open();
386                     }
387                 }
388             }).on('mousedown', function () {
389                 $this.needBlur = false;
390             });
391             this.$dropdown.on('click', '.city-select a', function () {
392                 var $select = $(this).parents('.city-select');
393                 var $active = $select.find('a.active');
394                 var last = $select.next().length === 0;
395                 $active.removeClass('active');
396                 $(this).addClass('active');
397                 if ($active.data('code') !== $(this).data('code')) {
398                     $select.data('item', {
399                         address: $(this).attr('title'), code: $(this).data('code')
400                     });
401                     $(this).trigger(EVENT_CHANGE);
402                     $this.feedText();
403                     $this.feedVal(true);
404                     if (last) {
405                         $this.close();
406                     }
407                 }
408             }).on('click', '.city-select-tab a', function () {
409                 if (!$(this).hasClass('active')) {
410                     var type = $(this).data('count');
411                     $this.tab(type);
412                 }
413             }).on('mousedown', function () {
414                 $this.needBlur = false;
415             });
416             if (this.$province) {
417                 this.$province.on(EVENT_CHANGE, (this._changeProvince = $.proxy(function () {
418                     if(this.output(CITY)){//判斷下一個tab是否有數據,沒有則關閉下拉
419                         $this.close();
420                         return;
421                     };
422                     this.output(CITY);
423                     this.output(DISTRICT);
424                     this.output(COUNTY);
425                     this.tab(CITY);
426                 }, this)));
427             }
428             if (this.$city) {
429                 this.$city.on(EVENT_CHANGE, (this._changeCity = $.proxy(function () {
430                     if(this.output(DISTRICT)){
431                         $this.close();
432                         return;
433                     };
434                     this.output(COUNTY);
435                     this.tab(DISTRICT);
436                 }, this)));
437             }
438 
439             if (this.$district) {
440                 this.$district.on(EVENT_CHANGE, (this._changeDistrict = $.proxy(function () {
441                     if(this.output(COUNTY)){
442                         $this.close();
443                         return;
444                     };
445                     this.tab(COUNTY);
446                 }, this)));
447             }
448         },
449         //顯示下拉
450         open: function (type) {
451             type = type || PROVINCE;
452             this.$dropdown.show();
453             this.$textspan.addClass('open').addClass('focus');
454             this.tab(type);
455         },
456         //關閉下拉
457         close: function (blur) {
458             this.$dropdown.hide();
459             this.$textspan.removeClass('open');
460             if (blur) {
461                 this.$textspan.removeClass('focus');
462             }
463         },
464         //解綁事件
465         unbind: function () {
466 
467             $(document).off('click', this._mouteclick);
468 
469             this.$element.off('change', this._changeElement);
470             this.$element.off('focus', this._focusElement);
471             this.$element.off('blur', this._blurElement);
472 
473             this.$textspan.off('click');
474             this.$textspan.off('mousedown');
475 
476             this.$dropdown.off('click');
477             this.$dropdown.off('mousedown');
478 
479             if (this.$province) {
480                 this.$province.off(EVENT_CHANGE, this._changeProvince);
481             }
482 
483             if (this.$city) {
484                 this.$city.off(EVENT_CHANGE, this._changeCity);
485             }
486 
487             if (this.$district) {
488                 this.$district.off(EVENT_CHANGE, this._changeDistrict);
489             }
490         },
491         //獲取選擇項信息
492         getText: function () {
493             var text = '';
494             this.$dropdown.find('.city-select')
495                 .each(function () {
496                     var item = $(this).data('item'),
497                         type = $(this).data('count');
498                     if (item) {
499                         text += ($(this).hasClass('province') ? '' : '/') + '<span class="select-item" data-count="' +
500                             type + '" data-code="' + item.code + '">' + item.address + '</span>';
501                     }
502                 });
503             return text;
504         },
505         getPlaceHolder: function () {
506             return this.$element.attr('placeholder') || this.options.placeholder;
507         },
508         //顯示placeholder或者選擇的區域
509         feedText: function () {
510             var text = this.getText();
511             if (text) {
512                 this.$textspan.find('>.placeholder').hide();
513                 this.$textspan.find('>.title').html(this.getText()).show();
514             } else {
515                 this.$textspan.find('>.placeholder').text(this.getPlaceHolder()).show();
516                 this.$textspan.find('>.title').html('').hide();
517             }
518         },
519         getCode: function (count) {
520             var obj = {}, arr = [];
521             this.$textspan.find('.select-item')
522                 .each(function () {
523                     var code = $(this).data('code');
524                     var count = $(this).data('count');
525                     obj[count] = code;
526                     arr.push(code);
527                 });
528             return count ? obj[count] : arr.join('/');
529         },
530         getVal: function () {
531             var text = '';
532             var code='';
533             this.$dropdown.find('.city-select')
534                 .each(function () {
535                     var item = $(this).data('item');
536                     if (item) {
537                         text += ($(this).hasClass('province') ? '' : '/') + item.address;
538                         code += ($(this).hasClass('province') ? '' : '_') + item.code;
539                     }
540                 });
541             $("#addrValue").val(code);
542             return text;
543         },
544         //input的value賦值
545         feedVal: function (trigger) {
546             this.$element.val(this.getVal());
547             if(trigger) {
548                 this.$element.trigger('cp:updated');
549             }
550         },
551         //輸出數據
552         output: function (type) {
553             var $this = this;
554             var options = this.options;
555             //var placeholders = this.placeholders;
556             var $select = this['$' + type];
557             var data = type === PROVINCE ? {} : [];
558             var item;
559             var districts;
560             var code;
561             var matched = null;
562             var value;
563             if (!$select || !$select.length) {
564                 return;
565             }
566             item = $select.data('item');
567             value = (item ? item.address : null) || options[type];
568             code = (
569                 type === PROVINCE ? 86 :
570                     type === CITY ? this.$province && this.$province.find('.active').data('code') :
571                         type === DISTRICT ? this.$city && this.$city.find('.active').data('c

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、Web 伺服器配置 Rewrite 2、環境需求 3、目錄結構 + app | - bootstrap.php | - config.php | + Index | + _App | + Controller | - _Controller.php | - Index.php | + Model ...
  • 單例模式是一種常見的設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。 比如,伺服器的配置信息寫在一個文件中online.conf中,客戶端通過一個 Config 的類來讀取配置文件的內容。如果在程式運行期間,有很多地方都 ...
  • swing之簡單登陸窗體的實現 幾點剛學時寫代碼犯得錯誤: 1.老是忘記佈局管理,這樣導致有時候界面只會出來你寫的其中一個組件 2.獲取密碼的時候不能只是簡單的getpassword去比較,要把獲取的東西轉換成String類型後再去比較 3.如果不寫setvisible,啥也不會出來 上兩張截圖吧: ...
  • 接上文 註釋的使用 在jinjia2模板中,使用{# #}進行代碼註釋,如下所示 運行後發現,註釋不會被render出來 去掉空行 兩種方法可以去掉jinjia2模板中的空白行,一是設置jinjia2的環境變數,如下 app.jinja_env.trim_blocks = True app.jinj ...
  • File 遞歸刪除文件夾中所有文件文件夾 又寫了一遍 找不同 ...
  • 本文將介紹如何使用虛擬機一步步從安裝Ubuntu到搭建Hadoop偽分散式集群。 本文主要參考:在VMware下安裝Ubuntu並部署Hadoop1.2.1分散式環境 - CSDN博客 一、所需的環境和軟體:(以下是我們的環境,僅供參考) 1. 操作系統:Windows 10 64位 2. 記憶體:4 ...
  • 在某種情況下,我們不得不進行整型等數據類型與字元串類型的轉換,比如,將“1234”轉換為整數,常規的我們可以使用atoi函數來進行轉換,或者是寫一個迴圈來做轉換,我們在這裡也可以使用sstream類來做轉換。示例代碼如下,演示了atoi和sstream的方法。 ...
  • 前言 朋友們, 大家好,我還是Rector,寫ASP.NET MVC 5系列文章 [\[一步一步創建ASP.NET MVC5程式Repository+Autofac+Automapper+SqlSugar\]][6] 的那個家伙。 今天為大家帶來本系列的第十篇文章。 本文知識要點 本文將要給大家分享 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...