function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var Util = require('../util'); var Category = require('./category'); var _require = require('../const'), FONT_FAMILY = _require.FONT_FAMILY; var DomUtil = Util.DomUtil; var Group = Util.Group; var CONTAINER_CLASS = 'g2-legend'; var TITLE_CLASS = 'g2-legend-title'; var LIST_CLASS = 'g2-legend-list'; var ITEM_CLASS = 'g2-legend-list-item'; var TEXT_CLASS = 'g2-legend-text'; var MARKER_CLASS = 'g2-legend-marker'; // find a dom node from the chidren of the node with className. function findNodeByClass(node, className) { return node.getElementsByClassName(className)[0]; } function getParentNode(node, className) { var nodeClass = node.className; if (Util.isNil(nodeClass)) { return node; } nodeClass = nodeClass.split(' '); if (nodeClass.indexOf(className) > -1) { return node; } if (node.parentNode) { if (node.parentNode.className === CONTAINER_CLASS) { return node.parentNode; } return getParentNode(node.parentNode, className); } return null; } function findItem(items, refer) { var rst = null; var value = refer instanceof Group ? refer.get('value') : refer; Util.each(items, function (item) { if (item.value === value) { rst = item; return false; } }); return rst; } var CatHtml = /*#__PURE__*/function (_Category) { _inheritsLoose(CatHtml, _Category); var _super = _createSuper(CatHtml); function CatHtml() { return _Category.apply(this, arguments) || this; } var _proto = CatHtml.prototype; _proto.getDefaultCfg = function getDefaultCfg() { var cfg = _Category.prototype.getDefaultCfg.call(this); return Util.mix({}, cfg, { /** * type 标识 * @type {String} */ type: 'category-legend', /** * html 容器 * @type {DOM} */ container: null, /** * 使用html时的外层模板 * @type {String} */ containerTpl: '
' + '

' + '' + '
', /** * html 模板 * @type {String|Function} */ itemTpl: '
  • ' + '' + '{value}
  • ', /** * html style * @type {Attrs} */ legendStyle: {}, /** * 图例文字样式 * @type {ATTRS} */ textStyle: { fill: '#333', fontSize: 12, textAlign: 'middle', textBaseline: 'top', fontFamily: FONT_FAMILY }, /** * 当文本太长时是否进行缩略 * @type {Boolean} */ abridgeText: false, /** * abridgeText 为 true 时,鼠标放置在 item 上时显示全称的悬浮 div 的 html 模板 * @type {String} */ tipTpl: '
    ', /** * abridgeText 为 true 时,鼠标放置在 item 上时显示全称的悬浮 div 的样式 * @type {Attrs} */ tipStyle: { display: 'none', fontSize: '12px', backgroundColor: '#fff', position: 'absolute', width: 'auto', height: 'auto', padding: '3px', boxShadow: '2px 2px 5px #888' }, /** * useHtml 为 true 时生效,用于自动定位 * @type {[type]} */ autoPosition: true }); }; _proto._init = function _init() { return; }; _proto.beforeRender = function beforeRender() { return; }; _proto.render = function render() { this._renderHTML(); } // user interaction ; _proto._bindEvents = function _bindEvents() { var _this = this; var legendWrapper = this.get('legendWrapper'); var itemListDom = findNodeByClass(legendWrapper, LIST_CLASS); if (this.get('hoverable')) { itemListDom.onmousemove = function (ev) { return _this._onMousemove(ev); }; itemListDom.onmouseout = function (ev) { return _this._onMouseleave(ev); }; } if (this.get('clickable')) { itemListDom.onclick = function (ev) { return _this._onClick(ev); }; } } // mouse move listener of an item // when mouse over an item, reduce the opacity of the other items. ; _proto._onMousemove = function _onMousemove(ev) { var items = this.get('items'); var target = ev.target; var targetClass = target.className; targetClass = targetClass.split(' '); if (targetClass.indexOf(CONTAINER_CLASS) > -1 || targetClass.indexOf(LIST_CLASS) > -1) { return; } var parentDom = getParentNode(target, ITEM_CLASS); var hoveredItem = findItem(items, parentDom.getAttribute('data-value')); if (hoveredItem) { // change the opacity of other items this.deactivate(); this.activate(parentDom.getAttribute('data-value')); this.emit('itemhover', { item: hoveredItem, currentTarget: parentDom, checked: hoveredItem.checked }); } else if (!hoveredItem) { // restore the opacity of all the items this.deactivate(); this.emit('itemunhover', ev); } return; } // mouse leave listener of an item ; _proto._onMouseleave = function _onMouseleave(ev) { // restore the opacity of all the items when mouse leave this.deactivate(); this.emit('itemunhover', ev); return; } // the click listener of an item ; _proto._onClick = function _onClick(ev) { var _this2 = this; var legendWrapper = this.get('legendWrapper'); var itemListDom = findNodeByClass(legendWrapper, LIST_CLASS); var unCheckedColor = this.get('unCheckColor'); var items = this.get('items'); var mode = this.get('selectedMode'); var childNodes = itemListDom.childNodes; var target = ev.target; var targetClass = target.className; targetClass = targetClass.split(' '); if (targetClass.indexOf(CONTAINER_CLASS) > -1 || targetClass.indexOf(LIST_CLASS) > -1) { return; } var parentDom = getParentNode(target, ITEM_CLASS); var textDom = findNodeByClass(parentDom, TEXT_CLASS); var markerDom = findNodeByClass(parentDom, MARKER_CLASS); var clickedItem = findItem(items, parentDom.getAttribute('data-value')); if (!clickedItem) { return; } var domClass = parentDom.className; var originColor = parentDom.getAttribute('data-color'); if (mode === 'single') { // 单选模式 // update checked status clickedItem.checked = true; // 其他图例项全部置灰 Util.each(childNodes, function (child) { if (child !== parentDom) { var childMarkerDom = findNodeByClass(child, MARKER_CLASS); childMarkerDom.style.backgroundColor = unCheckedColor; child.className = child.className.replace('checked', 'unChecked'); child.style.color = unCheckedColor; var childItem = findItem(items, child.getAttribute('data-value')); childItem.checked = false; } else { if (textDom) { textDom.style.color = _this2.get('textStyle').fill; } if (markerDom) { markerDom.style.backgroundColor = originColor; } parentDom.className = domClass.replace('unChecked', 'checked'); } }); } else { // 混合模式 var clickedItemChecked = domClass.indexOf('checked') !== -1; // domClass.includes('checked'); var count = 0; Util.each(childNodes, function (child) { if (child.className.indexOf('checked') !== -1) { // .includes('checked') count++; } }); if (!this.get('allowAllCanceled') && clickedItemChecked && count === 1) { this.emit('clicklastitem', { item: clickedItem, currentTarget: parentDom, checked: mode === 'single' ? true : clickedItem.checked }); return; } // 在判断最后一个图例后再更新checked状态,防止点击最后一个图例item时图例样式没有变化但是checked状态改变了 fix #422 clickedItem.checked = !clickedItem.checked; if (clickedItemChecked) { if (markerDom) { markerDom.style.backgroundColor = unCheckedColor; } parentDom.className = domClass.replace('checked', 'unChecked'); parentDom.style.color = unCheckedColor; } else { if (markerDom) { markerDom.style.backgroundColor = originColor; } parentDom.className = domClass.replace('unChecked', 'checked'); parentDom.style.color = this.get('textStyle').fill; } } this.emit('itemclick', { item: clickedItem, currentTarget: parentDom, checked: mode === 'single' ? true : clickedItem.checked }); return; } // activate an item by reduce the opacity of other items. // it is reserved for bi-direction interaction between charts / graph and legend ; _proto.activate = function activate(value) { var _this3 = this; var self = this; var items = self.get('items'); var item = findItem(items, value); var legendWrapper = self.get('legendWrapper'); var itemListDom = findNodeByClass(legendWrapper, LIST_CLASS); var childNodes = itemListDom.childNodes; childNodes.forEach(function (child) { var childMarkerDom = findNodeByClass(child, MARKER_CLASS); var childItem = findItem(items, child.getAttribute('data-value')); if (_this3.get('highlight')) { if (childItem === item && childItem.checked) { childMarkerDom.style.border = '1px solid #333'; return; } } else { if (childItem === item) { childMarkerDom.style.opacity = self.get('activeOpacity'); } else { if (childItem.checked) childMarkerDom.style.opacity = self.get('inactiveOpacity'); } } // if (childItem !== item && childItem.checked) { // if (this.get('highlight')) { // childMarkerDom.style.border = '1px solid #fff'; // } else childMarkerDom.style.opacity = 0.5; // } else { // if (this.get('highlight')) { // childMarkerDom.style.border = '1px solid #333'; // } else childMarkerDom.style.opacity = 1; // } }); return; } // restore the opacity of items // it is reserved for bi-direction interaction between charts / graph and legend ; _proto.deactivate = function deactivate() { var _this4 = this; var self = this; var legendWrapper = self.get('legendWrapper'); var itemListDom = findNodeByClass(legendWrapper, LIST_CLASS); var childNodes = itemListDom.childNodes; childNodes.forEach(function (child) { var childMarkerDom = findNodeByClass(child, MARKER_CLASS); if (_this4.get('highlight')) { childMarkerDom.style.border = '1px solid #fff'; } else { childMarkerDom.style.opacity = self.get('inactiveOpacity'); } }); return; }; _proto._renderHTML = function _renderHTML() { var _this5 = this; // const canvas = this.get('canvas'); var container = this.get('container'); // const outterNode = container.parentNode; var title = this.get('title'); var containerTpl = this.get('containerTpl'); var legendWrapper = DomUtil.createDom(containerTpl); var titleDom = findNodeByClass(legendWrapper, TITLE_CLASS); var itemListDom = findNodeByClass(legendWrapper, LIST_CLASS); // ul var unCheckedColor = this.get('unCheckColor'); var LEGEND_STYLE = Util.deepMix({}, { CONTAINER_CLASS: { height: 'auto', width: 'auto', position: 'absolute', overflowY: 'auto', fontSize: '12px', fontFamily: FONT_FAMILY, lineHeight: '20px', color: '#8C8C8C' }, TITLE_CLASS: { marginBottom: this.get('titleGap') + 'px', fontSize: '12px', color: '#333', // 默认样式 textBaseline: 'middle', fontFamily: FONT_FAMILY }, LIST_CLASS: { listStyleType: 'none', margin: 0, padding: 0, textAlign: 'center' }, LIST_ITEM_CLASS: { cursor: 'pointer', marginBottom: '5px', marginRight: '24px' }, MARKER_CLASS: { width: '9px', height: '9px', borderRadius: '50%', display: 'inline-block', marginRight: '4px', verticalAlign: 'middle' } }, this.get('legendStyle')); // fix:IE 9 兼容问题,先加入 legendWrapper // let container = this.get('container'); if (/^\#/.test(container) || typeof container === 'string' && container.constructor === String) { // 如果传入 dom 节点的 id var id = container.replace('#', ''); container = document.getElementById(id); container.appendChild(legendWrapper); } else { var _position = this.get('position'); var rangeStyle = {}; if (_position === 'left' || _position === 'right') { rangeStyle = { maxHeight: (this.get('maxLength') || container.offsetHeight) + 'px' }; } else { rangeStyle = { maxWidth: (this.get('maxLength') || container.offsetWidth) + 'px' }; } DomUtil.modifyCSS(legendWrapper, Util.mix({}, LEGEND_STYLE.CONTAINER_CLASS, rangeStyle, this.get(CONTAINER_CLASS))); container.appendChild(legendWrapper); } DomUtil.modifyCSS(itemListDom, Util.mix({}, LEGEND_STYLE.LIST_CLASS, this.get(LIST_CLASS))); // render title if (titleDom) { if (title && title.text) { titleDom.innerHTML = title.text; DomUtil.modifyCSS(titleDom, Util.mix({}, LEGEND_STYLE.TITLE_CLASS, this.get(TITLE_CLASS), title)); } else { legendWrapper.removeChild(titleDom); } } // 开始渲染图例项 var items = this.get('items'); var itemTpl = this.get('itemTpl'); var position = this.get('position'); var layout = this.get('layout'); var itemDisplay = position === 'right' || position === 'left' || layout === 'vertical' ? 'block' : 'inline-block'; var itemStyle = Util.mix({}, LEGEND_STYLE.LIST_ITEM_CLASS, { display: itemDisplay }, this.get(ITEM_CLASS)); var markerStyle = Util.mix({}, LEGEND_STYLE.MARKER_CLASS, this.get(MARKER_CLASS)); Util.each(items, function (item, index) { var checked = item.checked; var value = _this5._formatItemValue(item.value); var markerColor = item.marker.fill || item.marker.stroke; var color = checked ? markerColor : unCheckedColor; var domStr; if (Util.isFunction(itemTpl)) { domStr = itemTpl(value, color, checked, index); } else { domStr = itemTpl; } var itemDiv = Util.substitute(domStr, Util.mix({}, item, { index: index, checked: checked ? 'checked' : 'unChecked', value: value, color: color, originColor: markerColor, // @2018-07-09 by blue.lb 修复如果legend值中存在双引号"时, 导致的无法点击触发legend正常操作bug originValue: item.value.replace(/\"/g, '"') })); // li var itemDom = DomUtil.createDom(itemDiv); itemDom.style.color = _this5.get('textStyle').fill; var markerDom = findNodeByClass(itemDom, MARKER_CLASS); var textDom = findNodeByClass(itemDom, TEXT_CLASS); DomUtil.modifyCSS(itemDom, itemStyle); markerDom && DomUtil.modifyCSS(markerDom, markerStyle); // textDom && DomUtil.modifyCSS(textDom, this.get('textStyle')); if (!checked) { itemDom.style.color = unCheckedColor; if (markerDom) { markerDom.style.backgroundColor = unCheckedColor; } } itemListDom.appendChild(itemDom); // abridge the text if the width of the text exceeds the width of the item if (_this5.get('abridgeText')) { var text = value; // const itemWidth = parseFloat(this.get(ITEM_CLASS).width.substr(0, this.get(ITEM_CLASS).width.length - 2)); var itemWidth = itemDom.offsetWidth; var fs = _this5.get('textStyle').fontSize; if (isNaN(fs)) { // 6.5pt = 6.5 * 1/72 * 96 = 8.6px if (fs.indexOf('pt') !== -1) fs = parseFloat(fs.substr(0, fs.length - 2)) * 1 / 72 * 96;else if (fs.indexOf('px') !== -1) fs = parseFloat(fs.substr(0, fs.length - 2)); } var textWidth = fs * text.length; var letterNum = Math.floor(itemWidth / fs); if (itemWidth < 2 * fs) { // unable to contain '...' text = ''; } else if (itemWidth < textWidth) { // replace the tail as '... if (letterNum > 1) text = text.substr(0, letterNum - 1) + '...'; } textDom.innerText = text; // show the text tip while mouse hovering an item itemDom.addEventListener('mouseover', function () { var tipDom = findNodeByClass(legendWrapper.parentNode, 'textTip'); tipDom.style.display = 'block'; tipDom.style.left = itemDom.offsetLeft + itemDom.offsetWidth + 'px'; tipDom.style.top = itemDom.offsetTop + 15 + 'px'; tipDom.innerText = value; }); // hide the text tip while mouse leave the item itemDom.addEventListener('mouseout', function () { var tipDom = findNodeByClass(legendWrapper.parentNode, 'textTip'); tipDom.style.display = 'none'; }); } }); // append the tip div as a brother node of legend dom if (this.get('abridgeText')) { var tipTpl = this.get('tipTpl'); var tipDom = DomUtil.createDom(tipTpl); var tipDomStyle = this.get('tipStyle'); DomUtil.modifyCSS(tipDom, tipDomStyle); legendWrapper.parentNode.appendChild(tipDom); // hide the tip while mouse entering the tip dom tipDom.addEventListener('mouseover', function () { tipDom.style.display = 'none'; }); } this.set('legendWrapper', legendWrapper); }; _proto._adjustPositionOffset = function _adjustPositionOffset() { var autoPosition = this.get('autoPosition'); // @2018-12-29 by maplor. if autoPosition is false, don't set inline-style if (autoPosition === false) { return; } var position = this.get('position'); var offset = this.get('offset'); var offsetX = this.get('offsetX'); var offsetY = this.get('offsetY'); if (offsetX) offset[0] = offsetX; if (offsetY) offset[1] = offsetY; var legendWrapper = this.get('legendWrapper'); legendWrapper.style.left = position[0] + 'px'; legendWrapper.style.top = position[1] + 'px'; legendWrapper.style.marginLeft = offset[0] + 'px'; legendWrapper.style.marginTop = offset[1] + 'px'; }; _proto.getWidth = function getWidth() { return DomUtil.getOuterWidth(this.get('legendWrapper')); }; _proto.getHeight = function getHeight() { return DomUtil.getOuterHeight(this.get('legendWrapper')); }; _proto.move = function move(x, y) { if (!/^\#/.test(this.get('container'))) { DomUtil.modifyCSS(this.get('legendWrapper'), { left: x + 'px', top: y + 'px' }); this.set('x', x); this.set('y', y); } else { _Category.prototype.move.call(this, x, y); } }; _proto.destroy = function destroy() { var legendWrapper = this.get('legendWrapper'); if (legendWrapper && legendWrapper.parentNode) { legendWrapper.parentNode.removeChild(legendWrapper); } _Category.prototype.destroy.call(this); }; return CatHtml; }(Category); module.exports = CatHtml;