define(function (require) { var etpl = require('etpl'); var lib = require('esui/lib'); var main = require('esui/main'); var Control = require('esui/Control'); var regionData = require('./regionData'); require('etpl/tpl!./template.tpl'); // 每一行最多显示的省份数量 var LINE_MAX_NUM = 5; // 每个省份元素的宽度 var PROVINCE_ITEM_WIDTH = 90; // 父子容器除去省份元素外宽度差 var WIDTH_DIFF = 157; /** * 控件默认选项值 * @type {Object} */ var defaultOptions = { /** * 控件数据源 * @type {Array.<Object>} */ datasource: null, /** * 控件依附的元素ID * @type {string} */ attachToElement: '', /** * 默认选择的地域 * @type {?number} */ currentRegion: null, /** * 自定义地域 * @type {Array} */ customRegions: {} }; /** * 根据依附的元素定位控件主体元素 * @param {jQuery} attachElem */ function positionByAttachElement(attachElem) { var offset = attachElem.offset(); var container = this.getContainerElement(); var bodyWidth = $(document.body).outerWidth(); if (!offset) { return; } offset.top += attachElem.outerHeight(); // 若浮层超过屏幕宽度时,折向左边 if ((offset.left + container.width()) > bodyWidth) { offset.left -= container.width() - attachElem.outerWidth(); } this.positionAt(offset.left, offset.top); } /** * 地域单选组件 * @param {Object} options * @constructor * @extends Control */ function SingleRegion(options) { /** * 记录当前选择的地域 * @type {?Object} * @private */ this._currentRegion = null; /** * 记录当前选择的地域元素 * @type {?jQuery} * @private */ this._currentRegionElement = null; /** * 记录当前选择的地域元素的父级地域元素 * @type {?jQuery} * @private */ this._currentRegionParentElement = null; /** * 用户自定义的地域信息记录 * @type {Object} * @private */ this._customRegionInfo = {}; Control.apply(this, arguments); } /** * 继承于Control基类 */ lib.inherits(SingleRegion, Control); /** * 控件类型,始终为SingleRegion * @type {string} */ SingleRegion.prototype.type = 'SingleRegion'; /** * 获取当前选择的地域 * @returns {?Object} */ SingleRegion.prototype.getCurrentRegion = function () { return this._currentRegion; }; /** * 重置已选择的地域 */ SingleRegion.prototype.restoreRegion = function () { var currentRegionElement = this._currentRegionElement; var currentRegionParentElement = this._currentRegionParentElement; if (currentRegionElement) { currentRegionElement.find('input').prop('checked', false); } if (currentRegionParentElement) { this.helper.removePartClasses( 'parent-active', currentRegionParentElement[0] ); } this._currentRegion = null; this._currentRegionElement = null; this._currentRegionParentElement = null; }; /** * 设置当前已选地域 * @param {number} regionCode 地域编码 */ SingleRegion.prototype.selectRegion = function (regionCode) { var lastRegion = this.getCurrentRegion(); var currentRegion = this.getRegion(regionCode); // 如果没发生变化就啥也不干 if (lastRegion && (lastRegion.code === currentRegion.code)) { return; } this.restoreRegion(); var parentRegion = this.getParentRegion(regionCode); var containerElement = this.getContainerElement(); var currentRegionElement = containerElement.find( '[data-item-value="' + regionCode + '"]' ); var currentRegionParentElement = parentRegion ? containerElement .find('[data-item-value="' + parentRegion.code + '"]') : null; this._currentRegion = currentRegion; this._currentRegionElement = currentRegionElement; currentRegionElement.find('input').prop('checked', true); if (parentRegion) { this._currentRegionParentElement = currentRegionParentElement; this.helper.removePartClasses( 'parent-active', currentRegionParentElement[0] ); } // 用事件对调用者进行通知 this.fire('change', { last: lastRegion, current: currentRegion }); }; /** * 设置自定义地域 * @param {Object} regionInfo */ SingleRegion.prototype.setCustomRegion = function (regionInfo) { var customRegionInfo = this._customRegionInfo; if (!customRegionInfo) { customRegionInfo = this._customRegionInfo = {}; } customRegionInfo[regionInfo.code] = regionInfo; }; /** * 获取地域对象 * @param {number} regionCode 地域编码 * @returns {Object} */ SingleRegion.prototype.getRegion = function (regionCode) { var customRegionInfo = this._customRegionInfo; if (customRegionInfo.hasOwnProperty(regionCode)) { return customRegionInfo[regionCode]; } return regionData.getRegion(regionCode); }; /** * 获取父级地域对象 * @param {number} regionCode 地域编码 * @returns {Object} */ SingleRegion.prototype.getParentRegion = function (regionCode) { var region = this.getRegion(regionCode); if (!region.parent) { return null; } return this.getRegion(region.parent); }; /** * 初始化参数 * @param {Object} options * @override */ SingleRegion.prototype.initOptions = function (options) { var properties = $.extend(true, {}, defaultOptions, options); if (!properties.datasource) { properties.datasource = regionData.buildRegionList(); } var customRegions = properties.customRegions; for (var i = 0, customRegion; customRegion = customRegions[i++];) { this.setCustomRegion(customRegion); } this.setProperties(properties); }; /** * 初始化控件结构 * @override */ SingleRegion.prototype.initStructure = function () { // 默认隐藏控件 this.hide(); // 渲染控件内容 this.renderContent(); // 初始化事件 this.initDomEvents(); var currentRegion = this.currentRegion; if (typeof currentRegion === 'number') { this.selectRegion(currentRegion); } }; /** * 依附元素的点击事件 * @param {jQuery.Event} event */ function attachElementClickHandler(event) { var regionEntity = event.data.regionEntity; // 将地域选择控件元素展示在依附元素下方 positionByAttachElement.call(regionEntity, $(this)); // 地域选择控件的显示切换 regionEntity.toggle(); event.stopPropagation(); } /** * 控件元素的鼠标移入处理 * @param {Object} options 选项参数 */ function containerElementMouseEnter(options, me) { var elem = options.elem; var offset = elem.offset(); var subContainer = options.subContainer; var elemPosition = elem.position(); var bodyWidth = $(document.body).outerWidth(); if (subContainer.length > 0) { me.helper.addPartClasses('parent-active', elem[0]); } var left = elemPosition.left; var top = elemPosition.top + elem.outerHeight(); if ((offset.left + subContainer.outerWidth()) > bodyWidth) { left -= subContainer.outerWidth() - elem.outerWidth(); } subContainer.css({ left: left + 'px', top: top + 'px', 'z-index': Math.floor(+new Date / 1000) }).show(); } /** * 控件元素的鼠标移出处理 * @param {Object} options 选项参数 */ function containerElementMouseLeave(options, me) { var elem = options.elem; var subContainer = options.subContainer; var toElement = options.toElement; // 在子地域的container上绑定数据fromElement // 其值为鼠标在移入子地域container之前所在的元素 // 即一级地域的选择所在的元素 // 作用是在子地域container移出的时候 // 顺便将这个元素的class清除掉 subContainer.data('fromElement', elem); // 如果鼠标移出,则判断目标元素是否为相应的子地域 // 在目标元素不是相应的子地域元素时,将子地域的container隐藏 if (!toElement.closest(subContainer).length) { subContainer.hide(); me.helper.removePartClasses('parent-active', elem[0]); return; } } /** * 控件元素的鼠标响应代理事件 * @param {jQuery.Event} event */ function containerElementMouseoverHandler(event) { var elem = $(this); var type = event.type; var regionEntity = event.data.regionEntity; var regionCode = elem.attr('data-item-value'); var toElement = $(event.relatedTarget); var subContainer = $('.ui-singleregion-sub-container' + '[data-item-parent="' + regionCode + '"]'); /** * 组织必要的参数 * @type {Object} */ var data = { elem: elem, subContainer: subContainer, toElement: toElement, regionCode: regionCode }; if (type === 'mouseover') { containerElementMouseEnter(data, regionEntity); } else { containerElementMouseLeave(data, regionEntity); } event.stopPropagation(); } /** * 控件子地域的容器鼠标移出事件 * @param {jQuery.Event} event */ function subContainerMouseLeaveHandler(event) { var elem = $(this); var toElement = $(event.relatedTarget); var regionEntity = event.data.regionEntity; var originalFromElement = elem.data('fromElement'); if (!toElement.closest(elem.closest('div')).length) { regionEntity.helper.removePartClasses( 'parent-active', originalFromElement && originalFromElement[0] ); elem.hide(); elem.removeData('fromElement'); } event.stopPropagation(); } /** * 视窗大小改变的事件 * @param {jQuery.Event} event */ function windowResizeHandler(event) { var data = event.data; positionByAttachElement.call(data.regionEntity, data.attachElement); } /** * 全局委托点击事件 * @param {jQuery.Event} event */ function documentClickHandler(event) { var data = event.data; var target = $(event.target); if (!target.closest(data.containerElement).length) { data.regionEntity.hide(); } } /** * 控件元素点击事件 * @param {jQuery.Event} event */ function regionClickHandler(event) { var elem = $(this); var data = event.data; var regionEntity = data.regionEntity; var regionCode = elem.attr('data-item-value'); var regionDisabled = elem.attr('data-item-disabled') === 'true'; if (!regionDisabled) { regionEntity.selectRegion(regionCode); data.subContainerElement.hide(); } event.stopPropagation(); } /** * 初始化控件事件 */ SingleRegion.prototype.initDomEvents = function () { var me = this; var containerElement = me.getContainerElement(); var attachElement = me.getAttachElement(); var subContainerElement = containerElement.find( '.ui-singleregion-sub-container' ); var regionElement = containerElement.find( '[data-item-type="region"]' ); var parentRegionElement = containerElement.find( '[data-item-rank="province"]' ); var data = { regionEntity: me, containerElement: containerElement, attachElement: attachElement, subContainerElement: subContainerElement }; // 绑定依附元素的点击事件 attachElement.on('click', data, attachElementClickHandler); // 绑定地域元素的点击事件 regionElement.on('click', data, regionClickHandler); // 绑定控件子地域的容器鼠标移出事件 subContainerElement.on( 'mouseout', data, subContainerMouseLeaveHandler ); // 绑定控件主体的鼠标响应事件 parentRegionElement.on( 'mouseover mouseout', data, containerElementMouseoverHandler ); // 绑定window的resize事件 $(window).on('resize', data, windowResizeHandler); // 在document上委托click $(document).on('click', data, documentClickHandler); }; /** * 渲染控件内容 */ SingleRegion.prototype.renderContent = function () { var container = this.getContainerElement(); var datasource = this.get('datasource'); var content = etpl.render('library-ui-single-region', { list: datasource, className: { container: this.helper.getPartClassName('container'), area: this.helper.getPartClassName('area'), itemChina: this.helper.getPartClassName('item-for-china'), itemForeign: this.helper.getPartClassName('item-for-foreign'), sectorItem: this.helper.getPartClassName('sector-item'), provinceItem: this.helper.getPartClassName('province-item'), subContainer: this.helper.getPartClassName('sub-container'), subLast: this.helper.getPartClassName('sub-last') } }); container.html(content); this.changeContainerWidth(datasource, container); }; /** * 根据展示地域的个数设置容器宽度 * * @param {Object} data 显示的地域数据 * @param {jQuery} container 父容器 */ SingleRegion.prototype.changeContainerWidth = function (data, container) { var sectorContainer = container.find( '.ui-singleregion-sector-item' ); var length = 0; for (var i = 0; i < data.length; i++) { var item = data[i].provinces; var len = 0; for (var j = 0; j < item.length; j++) { if (item[j].status) { len++; } } if (len > length) { length = len; } } if (length < LINE_MAX_NUM) { sectorContainer.css('width', length * PROVINCE_ITEM_WIDTH); container.css( 'width', length * PROVINCE_ITEM_WIDTH + WIDTH_DIFF ); } return; } /** * 获取控件主体元素 * @returns {jQuery} */ SingleRegion.prototype.getContainerElement = function () { return $(this.main); }; /** * 获取控件所依附的元素 * @returns {jQuery} */ SingleRegion.prototype.getAttachElement = function () { return $(this.get('attachToElement')); }; /** * 控件定位 * @param {number} left * @param {number} top */ SingleRegion.prototype.positionAt = function (left, top) { this.getContainerElement().css({ left: left + 'px', top: top + 'px' }); }; /** * 销毁控件 * @override */ SingleRegion.prototype.dispose = function () { if (this.helper.isInStage('DISPOSED')) { return; } // 解除window的resize事件 $(window).off('resize', windowResizeHandler); // 解除document上委托click $(document).off('click', documentClickHandler); Control.prototype.dispose.apply(this, arguments); }; // 注册控件 main.register(SingleRegion); return SingleRegion; });
define(function (require) { var lib = require('esui/lib'); var u = require('underscore'); var InputControl = require('esui/InputControl'); var eoo = require('eoo'); var esui = require('esui/main'); var painters = require('esui/painters'); var $ = require('jquery'); require('esui/Label'); /** * FilterResult * * @extends Panel * @constructor */ var FilterResult = eoo.create( InputControl, { type: 'FilterResult', /** * 初始化配置 * * @protected * @override */ initOptions: function (options) { var properties = { datasource: [] }; u.extend(properties, options); this.setProperties(properties); }, /** * 初始化DOM结构 * * @protected * @override */ initStructure: function () { var controlHelper = this.helper; var mainEle = this.main; var html = '<div id="${filterPanelId}" class="${filterPanelStyle}">' + '<label id="${labelId}"></label>' + '<div id="${contentPanelId}" class="${contentPanelStyle}"></div>' + '</div>'; mainEle.innerHTML = lib.format( html, { filterPanelStyle: controlHelper.getPartClassName('panel'), filterPanelId: controlHelper.getId('items-wrapper-panel'), labelId: controlHelper.getId('items-label'), contentPanelId: controlHelper.getId('items-panel'), contentPanelStyle: controlHelper.getPartClassName('items-panel') } ); // 创建控件树 this.initChildren(mainEle); }, /** * 增加项 * @param {Object} item 选中项的数据 格式如: {value: '', text: ''} * @public */ addItem: function (item) { if (this.getItemByValue(item.value)) { return; } this.datasource.push(item); this.buildItems(); }, /** * 获取提示已选项Panel * @return {Panel} 提示已选项Panel * @private */ getSelectedItemsPanel: function () { var selectedPanelId = this.helper.getId('items-panel'); return this.viewContext.get(selectedPanelId); }, /** * 初始化事件交互 * * @protected * @override */ initEvents: function () { var me = this; this.helper.addDOMEvent( me.main, 'click', 'a', function (e) { e.preventDefault(); var $target = $(e.currentTarget); var value = $target.attr('data-value'); var text = $target.children(':first-child').text(); var item = { value: value, text: text }; me.removeItem(item); } ); }, /** * 移除选中项 * @param {Object} item 选中项的数据 格式如: {value: '', text: ''} * @param {HtmlElement} target 取消选中的元素 * @private */ removeItem: function (item) { if (!item) { return; } var selectedItem = this.getItemByValue(item.value); this.datasource = u.without(this.datasource, selectedItem); /** * @event select * * 移除时触发 */ this.fire('change', { item: item }); this.buildItems(); }, /** * 根据值获取整个选择项的数据 * @param {string} value 值 * @param {Object=} datasource 数据源 * @return {Object} item 选中项的数据 格式如: {value: '', text: ''} * @public */ getItemByValue: function (value) { var item; u.each(this.datasource, function (single, index) { if (single.value === value) { item = single; } }); return item; }, /** * 重渲染 * * @method * @protected * @override */ repaint: painters.createRepaint( InputControl.prototype.repaint, { name: ['datasource'], paint: function (resultPanel, datasource) { resultPanel.buildItems(); } }, { name: ['label'], paint: function (resultPanel, selectedLabel) { $(resultPanel.helper.getPart('items-label')).text(selectedLabel); } } ), /** * 根据datasource生成选择项 * @param {Array} datasource 选项列表数据源 * @private */ buildItems: function () { var html = '<a href="#" class="${style}" data-value="${value}">' + '<span>${text}</span>' + '<span class="${iconClass} ${removeClass}"></span>' + '</a>'; var s = ''; var helper = this.helper; u.forEach(this.datasource, function (item) { s += lib.format( html, { value: item.value, text: item.text, style: helper.getPartClassName('item'), iconClass: helper.getIconClass(), removeClass: helper.getPartClassName('remove') } ); }); var selectedItemsPanel = helper.getPart('items-panel'); $(selectedItemsPanel).html(s); }, /** * 获取选中的 * @return {Object} 选中的条件 */ getSelectedItems: function () { var items = []; u.each(this.datasource, function (item, index) { if (item.selected) { items.push(item); } }); return items; }, /** * 获取选中的值 * @return {Object} 选中项 */ getValue: function () { var items = this.getSelectedItems(); var valueArr = []; u.each(items, function (item, index) { valueArr.push(item.value); }); return valueArr; } } ); esui.register(FilterResult); return FilterResult; });
function (require) { // 引用创建SWF元素的帮助类 require('./helper/swfHelper'); var u = require('underscore'); var Control = require('esui/Control'); var eoo = require('eoo'); var esui = require('esui/main'); var $ = require('jquery'); // 引用Flash swf的路径通过AMD路径计算 var swfPath = require.toUrl('../resource/fClipboard.swf'); /** * CopyButton类定义 * * @class * @extends Control * * @constructor * * 创建新的CopyButton实例 * * @param {Object} [options] 组件参数 */ var CopyButton = eoo.create( Control, { /** * CopyButton类型用于注册到ESUI库 * * @override */ type: 'CopyButton', /** * 初始化传入参数 * * @param {Object} options 初始化参数 * @override */ initOptions: function (options) { var properties = { /** * @property {boolean} * * 是否把Flash Hover鼠标设置成小手 */ setHandCursor: true, /** * @property {string} * * 要拷贝到剪切板的字符串 */ content: '' }; u.extend(properties, options); this.$super([properties]); }, /** * @override */ initStructure: function () { var helper = this.helper; this.flashId = helper.getId('flash'); var jqFlashWrapper = $('<span id="' + helper.getId('flash-wrapper') + '"></span>'); var jqMainElement = $(this.main); // 创建Flash页面元素 jqFlashWrapper.append( $.flash.create( { id: this.flashId, swf: swfPath, width: '100%', height: '100%', wmode: 'transparent' } ) ); // 对齐元素 jqMainElement.append(jqFlashWrapper); jqMainElement.css('position', 'relative'); jqFlashWrapper.css({ position: 'absolute', top: 0, left: 0, bottom: 0, right: 0 }); }, /** * @override */ initEvents: function () { var me = this; me.copyScriptFun = me.id + '_proxy'; window[me.copyScriptFun] = u.bind(onCopyScript, me); checkFlashState.call(me, function () { /** * Flash元素完成初始化时触发 * * @event CopyButton#ready */ me.fire('ready'); }); }, /** * @override */ dispose: function () { var helper = this.helper; if (helper.isInStage('DISPOSED')) { return; } // 移除添加的DOM元素 $(this.main).css('position', ''); $('#' + helper.getId('flash-wrapper')).remove(); // 清除全局Flash Proxy函数 delete window[this.copyScriptFun]; this.$super(arguments); } } ); /** * 触发copy事件使用者从外部传入要拷贝到剪切板的内容 * * @return {string} 需要拷贝到剪切板的内容 * @private */ function onCopyScript() { /** * 值变更时触发 * * @event * @param {Object} e 事件参数 * @param {string} e.content CopyButton当前content的值 * * @example * copyButtonInstance.on('copy', function (e) { * // 上一次的值 * console.log(e.content); * this.content = 'new value to copy'; * ); */ this.fire('copy', { content: this.content }); return this.content; } /** * 循环检测 flash 的初始化情况,初始化后注册回调函数 * * @param {Function} callback 完成初始化后的回调函数 */ function checkFlashState(callback) { var me = this; var flash = $('#' + me.flashId)[0]; if (flash.flashInit && flash.flashInit()) { flash.setHandCursor(me.setHandCursor); flash.setContentFuncName(me.copyScriptFun); if (callback) { callback(); } } else { setTimeout( function () { checkFlashState.call(me, callback); }, 10 ); } } esui.register(CopyButton); return CopyButton; }
function (require) { var u = require('underscore'); var $ = require('jquery'); var esui = require('esui/main'); var InputControl = require('esui/InputControl'); var eoo = require('eoo'); var painters = require('esui/painters'); /** * 单选框 * * @extends InputControl * @constructor */ var Radio = eoo.create(InputControl, { /** * 控件类型,始终为`"Radio"` * * @type {string} * @readonly * @override */ type: 'Radio', /** * 初始化配置 * * @protected * @override */ initOptions: function (options) { var properties = { /** * @property {string} [selectedValue=''] * * Radio的Value */ selectedValue: '' }; u.extend(properties, options); properties.name = properties.name || this.main.getAttribute('name'); this.setProperties(properties); }, /** * 初始化DOM结构 * * @protected * @override */ initStructure: function () { var name = this.name; var inputs = $('input[name="' + name + '"]'); var id = this.helper.getId(); var classes = this.helper.getPartClasses('custom'); var count = 0; u.each( inputs, function (input) { input = $(input); var inputId = id + '-part' + count++; inputId = input.attr('id') || inputId; input.attr('id', inputId); input.wrap('<div class="' + classes + '"></div>'); var labelValue = input.data('label'); var label = $('<label for="' + inputId + '">' + labelValue + '</label>'); input.after(label); } ); }, /** * 初始化事件交互 * * @protected * @override */ initEvents: function () { var name = this.name; var inputs = $('input[name="' + name + '"]'); var that = this; inputs.on('change', function () { var value = $('input[name="' + name + '"]:checked').val(); that.setValue(value); that.fire('change', { value: value }); }); }, /** * 重渲染 * * @method * @protected * @override */ repaint: painters.createRepaint( InputControl.prototype.repaint, { /** * @property {string} selectedValue */ name: 'selectedValue', paint: function (box, selectedValue) { var name = box.name; $('input[name="' + name + '"][value="' + selectedValue + '"]').prop('checked', true); } }, { name: 'disabled', paint: function (box, disabled) { var name = box.name; var inputs = $('input[name="' + name + '"]'); if (disabled) { inputs.prop('disabled', true); } else { inputs.prop('disabled', false); } } } ) }); esui.register(Radio); return Radio; }