Authored by yyq

找回地址联动

/**
* 区域城市级联选择
* @author: dongjinhu(jinhu.dong@yoho.cn)
* @date: 2016/06/30
* @desc:
* 1. 为了减少库的复杂度,应用层的地址接口应该统一并且固定
* @examle:
* CascadingAddress({
* el: '#address',
* resources: 'areas',
* url: '', // 初始化数据请求
* onCreated: function () {} // 初始化完成回调
* })
*/
var $ = require('yoho-jquery');
// 默认配置
var settings = {
url: '',
containerClass: 'cascading-address',
levels: 3,
resources: 'areas',
names: ['province', 'city', 'district'],
indicators: ['请选择省份', '请选择城市', '请选择区/县'],
defaultDes: '加载中...',
ajaxSettings: {
type: 'GET',
url: '',
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}
};
// 显示或隐藏下拉区域
function toggleDistItem() {
var $this = $(this),
resetHeight = $this.css('height'),
openHeight = (parseInt(resetHeight.match(/\d*/)[0], 10) + 5) + 'px',
openAndResetHeight = (parseInt(resetHeight.match(/\d*/)[0], 10) - 5) + 'px';
if ($this.hasClass('closed')) {
// 如果有其他开着,先关掉
$('.items-indicator .open').each(function() {
$(this).find('.iconfont').replaceWith('<span class="iconfont up">&#xe60a;</span>')
.end()
.removeClass('open')
.addClass('closed')
.css({
height: resetHeight
}).next().hide();
});
// open
$this.find('.iconfont').replaceWith('<span class="iconfont up">&#xe609;</span>')
.end()
.removeClass('closed')
.addClass('open')
.css({
height: openHeight
})
.next()
.show();
// 有视觉差
// setTimeout(function(){
// $('.items-panel').slideDown('fast');
// }, 300)
} else {
// close
$this.find('.iconfont').replaceWith('<span class="iconfont up">&#xe60a;</span>')
.end()
.removeClass('open')
.addClass('closed')
.css({
height: openAndResetHeight
}).next().hide();
}
}
// 重置下一级文本显示和值
function resetNextLevel(level, config) {
$('#level_' + level + '_panel').empty()
.addClass('empty')
.text(config.defaultDes)
.prev().find('.indicator-name')
.text(config.indicators[config.levels - level - 1])
.next().val('');
}
// 获取初始化数据
function fetchInitialData(evt, config, level) {
var distItem, // 请选择...
distItemAreaId = $('.items-indicator .open input').val(),
ajaxSettings = $.extend({}, config.ajaxSettings, {
url: config.url
});
var ulElement = $('<ul/>'),
liElement,
distElement;
var urlArr;
// 当前选中区域id
var currAreaId,
currPanel;
$.ajax(ajaxSettings).done(function(res) {
// 渲染后台区域信息列表
$(res.data).each(function(index, item) {
liElement = $('<li/>');
$('<span class="check-icon iconfont">&#xe60b;</span>').appendTo(liElement);
$('<span/>', {
class: 'dist-name',
title: item.text,
text: item.text,
id: 'area_' + item.value
}).appendTo(liElement);
liElement.appendTo(ulElement);
});
// 填充下拉
if (level >= 0) {
currPanel = $('#level_' + level + '_panel');
ulElement.appendTo($(config.el).find('#level_' + level + '_panel').empty().removeClass('empty'));
}
// 选择区域
currPanel.off('click', '.dist-name').on('click', '.dist-name', function() {
distElement = $(this);
currAreaId = distElement.attr('id').split('_')[1];
distItem = $('#level_' + level + '_panel').prev();
if (distElement.hasClass('checked')) {
// TODO
// distElement.removeClass('checked');
} else {
currPanel.find('span.checked').removeClass('checked').prev().hide();
distElement.addClass('checked').prev().show();
distItem.find('.indicator-name')
.html(distElement.text())
.next()
.val(currAreaId);
// 填充下一级
if (level < 0) {
level = distElement.parents('.items-panel').attr('id').split('_')[1];
}
urlArr = config.url.split(config.resources + '/');
urlArr[1] = currAreaId;
config.url = urlArr.join(config.resources + '/');
// 选择之后关闭当前panel
// distItem.trigger('click');
// 当前点击的和已选择的不同,再渲染下一级目录
if (level && distItemAreaId !== currAreaId) {
resetNextLevel(level - 1, config);
$(config.el).trigger('ca.afterInit', [config, level - 1]);
}
}
});
}).fail(function() {
// 如果出错,将下级所有都重置
var from = level;
while (from >= 0) {
resetNextLevel(from, config);
from--;
}
});
}
// 构造器
function CascadingAddress(options) {
var widget = this,
element;
widget.config = $.extend(true, {}, settings, options); // Object.assign({}, settings, options);
element = widget.element = $(widget.config.el);
element.on('ca.afterInit', fetchInitialData);
element.on('click', '.dist-item', toggleDistItem);
// 绑定自定义事件处理
$.each(widget.config, function(key, value) {
if ($.isFunction(value)) {
element.on('ca.' + key, function(evt, params) {
// 处理自定义事件
return value(evt, element, params);
});
}
});
// 初始化
this.init();
}
// 初始化
CascadingAddress.prototype.init = function() {
// 配置
var config = this.config,
el = this.element,
target = el.addClass(config.containerClass),
levels = config.levels;
// DOM相关
var names = config.names,
indicators = config.indicators,
distItem,
inputName,
indicatorName;
// 省份,城市,区县容器
var distItemContainer = $('<ul class="items-indicator"/>'),
liElement,
distPanel;
// ======生成DOM结构======
while (levels--) {
indicatorName = indicators[config.levels - levels - 1];
// li element
liElement = $('<li/>');
// div element
distItem = $('<div></div>', {
class: 'dist-item closed'
});
// 标签
$('<span/>', {
class: 'indicator-name',
text: indicatorName
}).appendTo(distItem);
// input element
inputName = names[config.levels - levels - 1];
$('<input/>', {
type: 'hidden',
name: inputName,
id: inputName,
value: ''
}).appendTo(distItem);
// icon element
$('<span class="iconfont">&#xe60a;</span>').appendTo(distItem);
distItem.appendTo(liElement);
// 省份城市区县选择panel
distPanel = $('<div/>', {
class: 'items-panel empty',
id: 'level_' + levels + '_panel',
text: config.defaultDes
});
distPanel.appendTo(liElement);
liElement.appendTo(distItemContainer);
}
distItemContainer.appendTo(target);
// ======生成DOM结构======
// 获取初始化数据
el.trigger('ca.afterInit', [config, config.levels - 1]);
// 初始化完成,提供回调执行
el.trigger('ca.onCreated');
};
module.exports = function(options) {
return new CascadingAddress(options);
};
... ...