Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/component/legend/LegendView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ class LegendView extends ComponentView {
},
onclick() {
api.dispatchAction({
type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect'
type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect',
legendId: legendModel.id
});
}
});
Expand Down
94 changes: 58 additions & 36 deletions src/component/legend/legendAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,59 +17,81 @@
* under the License.
*/

// @ts-nocheck
import {curry, each, hasOwn} from 'zrender/src/core/util';
import { EChartsExtensionInstallRegisters } from '../../extension';
import { Payload } from '../../util/types';
import type GlobalModel from '../../model/Global';
import type LegendModel from './LegendModel';

import {curry, each} from 'zrender/src/core/util';
type LegendSelectMethodNames = 'select' | 'unSelect' | 'toggleSelected' | 'allSelect' | 'inverseSelect';

function legendSelectActionHandler(methodName, payload, ecModel) {
const selectedMap = {};
const isToggleSelect = methodName === 'toggleSelected';
let isSelected;
// Update all legend components
ecModel.eachComponent('legend', function (legendModel) {
if (isToggleSelect && isSelected != null) {
// Force other legend has same selected status
// Or the first is toggled to true and other are toggled to false
// In the case one legend has some item unSelected in option. And if other legend
// doesn't has the item, they will assume it is selected.
legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
}
else if (methodName === 'allSelect' || methodName === 'inverseSelect') {
function legendSelectActionHandler(methodName: LegendSelectMethodNames, payload: Payload, ecModel: GlobalModel) {
const isAllSelect = methodName === 'allSelect' || methodName === 'inverseSelect';
const selectedMap: Record<string, boolean> = {};

const actionLegendIndices: number[] = [];
ecModel.eachComponent({ mainType: 'legend', query: payload }, function (legendModel: LegendModel) {
if (isAllSelect) {
legendModel[methodName]();
}
else {
legendModel[methodName](payload.name);
isSelected = legendModel.isSelected(payload.name);
}
const legendData = legendModel.getData();
each(legendData, function (model) {
const name = model.get('name');
// Wrap element
if (name === '\n' || name === '') {
return;
}
const isItemSelected = legendModel.isSelected(name);
if (selectedMap.hasOwnProperty(name)) {
// Unselected if any legend is unselected
selectedMap[name] = selectedMap[name] && isItemSelected;
}
else {
selectedMap[name] = isItemSelected;
}

makeSelectedMap(legendModel, selectedMap);

actionLegendIndices.push(legendModel.componentIndex);
});

const allSelectedMap: Record<string, boolean> = {};

// make selectedMap from all legend components
ecModel.eachComponent('legend', function (legendModel: LegendModel) {
each(selectedMap, function (isSelected, name) {
// Force other legend has same selected status
// Or the first is toggled to true and other are toggled to false
// In the case one legend has some item unSelected in option. And if other legend
// doesn't has the item, they will assume it is selected.
legendModel[isSelected ? 'select' : 'unSelect'](name);
});

makeSelectedMap(legendModel, allSelectedMap);
});

// Return the event explicitly
return (methodName === 'allSelect' || methodName === 'inverseSelect')
return isAllSelect
? {
selected: selectedMap
selected: selectedMap,
// return legendIndex array to tell the developers which legends are allSelect / inverseSelect
legendIndex: actionLegendIndices
}
: {
name: payload.name,
selected: selectedMap
};
}

export function installLegendAction(registers) {
function makeSelectedMap(legendModel: LegendModel, out?: Record<string, boolean>) {
const selectedMap: Record<string, boolean> = out || {};
each(legendModel.getData(), function (model) {
const name = model.get('name');
// Wrap element
if (name === '\n' || name === '') {
return;
}
const isItemSelected = legendModel.isSelected(name);
if (hasOwn(selectedMap, name)) {
// Unselected if any legend is unselected
selectedMap[name] = selectedMap[name] && isItemSelected;
}
else {
selectedMap[name] = isItemSelected;
}
});
return selectedMap;
}

export function installLegendAction(registers: EChartsExtensionInstallRegisters) {
/**
* @event legendToggleSelect
* @type {Object}
Expand Down Expand Up @@ -113,4 +135,4 @@ export function installLegendAction(registers) {
'legendUnSelect', 'legendunselected',
curry(legendSelectActionHandler, 'unSelect')
);
}
}
136 changes: 136 additions & 0 deletions test/legend-action.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/runTest/actions/__meta__.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/runTest/actions/legend-action.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.