Authored by 姜枫

merge

@@ -100,16 +100,6 @@ @@ -100,16 +100,6 @@
100 100
101 <p class="title">9. 分页组件</p> 101 <p class="title">9. 分页组件</p>
102 <div style="border: 1px solid #000; height: 200px; padding: 5px;"> 102 <div style="border: 1px solid #000; height: 200px; padding: 5px;">
103 - <pre>  
104 - 全局安装json-server  
105 -  
106 - npm i -g json-server  
107 -  
108 - 启动  
109 -  
110 - json-server --watch mock/address.json  
111 -  
112 - </pre>  
113 {{{ pagination paginationOpts }}} 103 {{{ pagination paginationOpts }}}
114 </div> 104 </div>
115 105
@@ -161,6 +151,7 @@ @@ -161,6 +151,7 @@
161 151
162 <p style="margin-top: 20px;">14. 区域/选择地址组件</p> 152 <p style="margin-top: 20px;">14. 区域/选择地址组件</p>
163 <div style="padding: 5px; height: 300px;"> 153 <div style="padding: 5px; height: 300px;">
  154 + <p>使用手册详见yohoblk/public/js/plugins/README.md</p>
164 <div id="address"></div> 155 <div id="address"></div>
165 </div> 156 </div>
166 157
  1 +### 组件使用手册
  2 +
  3 +1. 地址选择组件
  4 +
  5 + 全局安装json-server模拟服务端返回数据
  6 +
  7 + npm i -g json-server
  8 +
  9 + 启动
  10 +
  11 + json-server --watch mock/address.json
  12 +
  13 + API使用:
  14 +
  15 + var address = cascadingAddress({
  16 + el: '#address',
  17 + url: 'http://localhost:3000/areas/0',
  18 + resource: 'areas'
  19 + });
  20 +
  21 + 获取选择地址文本:
  22 +
  23 + address.getAreaLabels()
  24 +
  25 + 获取选择地址areaId:
  26 +
  27 + address.getAreaIds()
  28 +
  29 + 设置地址:
  30 +
  31 + address.setAddress({
  32 + province: '32', // 省
  33 + city: '3201', // 市
  34 + dist: '320102' // 区县
  35 + });
  36 +
  37 + 开发者: 董金虎
@@ -78,6 +78,14 @@ function toggleDistItem() { @@ -78,6 +78,14 @@ function toggleDistItem() {
78 } 78 }
79 } 79 }
80 80
  81 +// 设置请求URL
  82 +function setRequestUrl(config, areaId) {
  83 + var urlArr = config.url.split(config.resources + '/');
  84 +
  85 + urlArr[1] = areaId;
  86 + return urlArr.join(config.resources + '/');
  87 +}
  88 +
81 // 重置下一级文本显示和值 89 // 重置下一级文本显示和值
82 function resetNextLevel(level, config) { 90 function resetNextLevel(level, config) {
83 $('#level_' + level + '_panel').empty() 91 $('#level_' + level + '_panel').empty()
@@ -88,23 +96,57 @@ function resetNextLevel(level, config) { @@ -88,23 +96,57 @@ function resetNextLevel(level, config) {
88 .next().val(''); 96 .next().val('');
89 } 97 }
90 98
  99 +// 选择特定省份,城市,或区县
  100 +function selectDistItem(options) {
  101 + var level = options.level, // 当前级别
  102 + distElement = options.target, // 选择特定项
  103 + currAreaId = distElement.attr('id').split('_')[1], // 当前选择areaId
  104 + distItem = $('#level_' + level + '_panel').prev(), // 请选择...
  105 + currPanel = options.panel, // 当前区域列表项
  106 + distItemAreaId = options.distItemAreaId, // 当前选中areaId
  107 + config = options.config;
  108 +
  109 + if (distElement.hasClass('checked')) {
  110 + // TODO
  111 + // distElement.removeClass('checked');
  112 + } else {
  113 + currPanel.find('span.checked').removeClass('checked').prev().hide();
  114 + distElement.addClass('checked').prev().show();
  115 + distItem.find('.indicator-name')
  116 + .html(distElement.text())
  117 + .next()
  118 + .val(currAreaId);
  119 +
  120 + // 填充下一级
  121 + if (level < 0) {
  122 + level = distElement.parents('.items-panel').attr('id').split('_')[1];
  123 + }
  124 +
  125 + config.url = setRequestUrl(config, currAreaId);
  126 +
  127 + // 选择之后关闭当前panel
  128 + // distItem.trigger('click');
  129 +
  130 + // 当前点击的和已选择的不同,再渲染下一级目录
  131 + if (level && distItemAreaId !== currAreaId) {
  132 + resetNextLevel(level - 1, config);
  133 + $(config.el).trigger('ca.afterInit', [config, level - 1]);
  134 + }
  135 + }
  136 +}
  137 +
91 // 获取初始化数据 138 // 获取初始化数据
92 function fetchInitialData(evt, config, level) { 139 function fetchInitialData(evt, config, level) {
93 - var distItem, // 请选择...  
94 - distItemAreaId = $('.items-indicator .open input').val(), 140 + var distItemAreaId = $('.items-indicator .open input').val(),
95 ajaxSettings = $.extend({}, config.ajaxSettings, { 141 ajaxSettings = $.extend({}, config.ajaxSettings, {
96 url: config.url 142 url: config.url
97 }); 143 });
98 144
99 var ulElement = $('<ul/>'), 145 var ulElement = $('<ul/>'),
100 - liElement,  
101 - distElement; 146 + liElement;
102 147
103 - var urlArr;  
104 -  
105 - // 当前选中区域id  
106 - var currAreaId,  
107 - currPanel; 148 + // 当前选中区域列表
  149 + var currPanel;
108 150
109 $.ajax(ajaxSettings).done(function(res) { 151 $.ajax(ajaxSettings).done(function(res) {
110 // 渲染后台区域信息列表 152 // 渲染后台区域信息列表
@@ -130,40 +172,85 @@ function fetchInitialData(evt, config, level) { @@ -130,40 +172,85 @@ function fetchInitialData(evt, config, level) {
130 172
131 // 选择区域 173 // 选择区域
132 currPanel.off('click', '.dist-name').on('click', '.dist-name', function() { 174 currPanel.off('click', '.dist-name').on('click', '.dist-name', function() {
133 - distElement = $(this);  
134 - currAreaId = distElement.attr('id').split('_')[1];  
135 - distItem = $('#level_' + level + '_panel').prev(); 175 + selectDistItem({
  176 + level: level,
  177 + target: $(this),
  178 + panel: currPanel,
  179 + distItemAreaId: distItemAreaId,
  180 + config: config
  181 + });
  182 + });
  183 + }).fail(function() {
  184 + // 如果出错,将下级所有都重置
  185 + var from = level;
  186 +
  187 + while (from >= 0) {
  188 + resetNextLevel(from, config);
  189 + from--;
  190 + }
  191 + });
  192 +}
  193 +
  194 +// 设置地址
  195 +function setAddress(evt, config, level, areaId) {
  196 + var ajaxSettings = $.extend({}, config.ajaxSettings, {
  197 + url: config.url
  198 + }),
  199 + liElement,
  200 + ulElement = $('<ul/>'),
  201 + currPanel,
  202 + label,
  203 + distVal,
  204 + distItemAreaId = $('.items-indicator .open input').val();
  205 +
  206 +
  207 + $.ajax(ajaxSettings).done(function(res) {
  208 + $(res.data).each(function(index, item) {
  209 + liElement = $('<li/>');
136 210
137 - if (distElement.hasClass('checked')) {  
138 - // TODO  
139 - // distElement.removeClass('checked'); 211 + // 设置目标区域check状态
  212 + if (item.value === areaId) {
  213 + label = item.text;
  214 + distVal = item.value;
  215 +
  216 + $('<span class="check-icon iconfont" style="display: inline;">&#xe60b;</span>').appendTo(liElement);
  217 + $('<span/>', {
  218 + class: 'dist-name checked',
  219 + title: label,
  220 + text: label,
  221 + id: 'area_' + item.value
  222 + }).appendTo(liElement);
140 } else { 223 } else {
141 - currPanel.find('span.checked').removeClass('checked').prev().hide();  
142 - distElement.addClass('checked').prev().show();  
143 - distItem.find('.indicator-name')  
144 - .html(distElement.text())  
145 - .next()  
146 - .val(currAreaId);  
147 -  
148 - // 填充下一级  
149 - if (level < 0) {  
150 - level = distElement.parents('.items-panel').attr('id').split('_')[1];  
151 - }  
152 -  
153 - urlArr = config.url.split(config.resources + '/');  
154 - urlArr[1] = currAreaId;  
155 - config.url = urlArr.join(config.resources + '/');  
156 -  
157 - // 选择之后关闭当前panel  
158 - // distItem.trigger('click');  
159 -  
160 - // 当前点击的和已选择的不同,再渲染下一级目录  
161 - if (level && distItemAreaId !== currAreaId) {  
162 - resetNextLevel(level - 1, config);  
163 - $(config.el).trigger('ca.afterInit', [config, level - 1]);  
164 - } 224 + $('<span class="check-icon iconfont">&#xe60b;</span>').appendTo(liElement);
  225 + $('<span/>', {
  226 + class: 'dist-name',
  227 + title: item.text,
  228 + text: item.text,
  229 + id: 'area_' + item.value
  230 + }).appendTo(liElement);
165 } 231 }
  232 +
  233 + liElement.appendTo(ulElement);
  234 +
  235 + ulElement.appendTo($(config.el).find('#level_' + level + '_panel').empty().removeClass('empty'));
166 }); 236 });
  237 +
  238 + // 设置label文本 和 设置areaId
  239 + currPanel = $('#level_' + level + '_panel');
  240 + currPanel.prev().find('.indicator-name').text(label)
  241 + .next().val(distVal);
  242 +
  243 + // 侦听选择
  244 + currPanel.off('click', '.dist-name').on('click', '.dist-name', function() {
  245 + selectDistItem({
  246 + level: level,
  247 + target: $(this),
  248 + panel: currPanel,
  249 + distItemAreaId: distItemAreaId,
  250 + config: config
  251 + });
  252 + });
  253 +
167 }).fail(function() { 254 }).fail(function() {
168 // 如果出错,将下级所有都重置 255 // 如果出错,将下级所有都重置
169 var from = level; 256 var from = level;
@@ -185,6 +272,7 @@ function CascadingAddress(options) { @@ -185,6 +272,7 @@ function CascadingAddress(options) {
185 272
186 element.on('ca.afterInit', fetchInitialData); 273 element.on('ca.afterInit', fetchInitialData);
187 element.on('click', '.dist-item', toggleDistItem); 274 element.on('click', '.dist-item', toggleDistItem);
  275 + element.on('ca.setAddr', setAddress);
188 276
189 // 绑定自定义事件处理 277 // 绑定自定义事件处理
190 $.each(widget.config, function(key, value) { 278 $.each(widget.config, function(key, value) {
@@ -274,6 +362,83 @@ CascadingAddress.prototype.init = function() { @@ -274,6 +362,83 @@ CascadingAddress.prototype.init = function() {
274 el.trigger('ca.onCreated'); 362 el.trigger('ca.onCreated');
275 }; 363 };
276 364
  365 +// 获取地址文本
  366 +CascadingAddress.prototype.getAreaLabels = function() {
  367 + var el = $(this.config.el),
  368 + result = [];
  369 +
  370 + el.find('.indicator-name').each(function() {
  371 + if ($(this).next().val() !== '') {
  372 + result.push($(this).text());
  373 + }
  374 + });
  375 +
  376 + return result.join(',');
  377 +};
  378 +
  379 +// 获取地址ID
  380 +CascadingAddress.prototype.getAreaIds = function() {
  381 + var el = $(this.config.el),
  382 + result = [],
  383 + target;
  384 +
  385 + el.find('input').each(function() {
  386 + target = $(this);
  387 + if (target.val() !== '') {
  388 + result.push($(this).val());
  389 + }
  390 + });
  391 +
  392 + if (result.length) {
  393 + return result.join(',');
  394 + } else {
  395 + return '';
  396 + }
  397 +};
  398 +
  399 +// 设置区域
  400 +// {
  401 +// "province": "32",
  402 +// "city": "3201",
  403 +// "dist": "320102"
  404 +// }
  405 +CascadingAddress.prototype.setAddress = function(targetAddr) {
  406 + var key,
  407 + distIds = ['0'], // 省份请求areaId=0
  408 + distLen,
  409 + cursor, // 游标
  410 + currentLevels = $('.items-indicator>li').length, // 目前存在几级
  411 + areaId, // 请求areaId
  412 + defaultId, // 设置areaId
  413 + config = this.config,
  414 + $el = $(config.el);
  415 +
  416 + if (typeof targetAddr === 'object') {
  417 + for (key in targetAddr) {
  418 + if (targetAddr.hasOwnProperty(key)) {
  419 + distIds.push(targetAddr[key]);
  420 + }
  421 + }
  422 +
  423 + // 标识需要渲染几级
  424 + distLen = distIds.sort().length;
  425 + cursor = distLen;
  426 +
  427 + // 最后一个level是0
  428 + while (distLen > 1) {
  429 + // 请求从array[0], 判断值从array[1]
  430 + areaId = distIds[cursor - distLen];
  431 + defaultId = distIds[cursor - distLen + 1];
  432 + config.url = setRequestUrl(config, areaId);
  433 + $el.trigger('ca.setAddr', [config, currentLevels - 1, defaultId]);
  434 + distLen--;
  435 + currentLevels--;
  436 + }
  437 + } else {
  438 + console.error('target address must be a json object');
  439 + }
  440 +};
  441 +
277 module.exports = function(options) { 442 module.exports = function(options) {
278 return new CascadingAddress(options); 443 return new CascadingAddress(options);
279 }; 444 };