diff --git a/src/visualizationManager.ts b/src/visualizationManager.ts index 6fc298611..012bc80df 100644 --- a/src/visualizationManager.ts +++ b/src/visualizationManager.ts @@ -14,24 +14,26 @@ declare type VisualizerConstructor = new ( */ export class VisualizationManager { static alternativesVisualizer: any = undefined; - static vizualizers: { [index: string]: Array } = {}; + static vizualizers: { [index: string]: Array<{ ctor: VisualizerConstructor, index: number }> } = {}; /** * Registers a visualizer for a specified question type. * * [View Demo](https://surveyjs.io/dashboard/examples/visualize-answers-from-text-entry-fields-with-charts/ (linkStyle)) * @param questionType A question [type](https://surveyjs.io/form-library/documentation/api-reference/question#getType). * @param constructor A function that returns a visualizer constructor to register. + * @param index A zero-based index that specifies the visualizer's position in the visualizer list for the specified question type. Pass `0` to the insert the visualizer at the beginning of the list and use it by default. If `index` is not specified, the visualizer is added to the end of the list. */ public static registerVisualizer( questionType: string, - constructor: VisualizerConstructor + constructor: VisualizerConstructor, + index = Number.MAX_VALUE ) { let visualizers = VisualizationManager.vizualizers[questionType]; if (!visualizers) { visualizers = []; VisualizationManager.vizualizers[questionType] = visualizers; } - visualizers.push(constructor); + visualizers.push({ ctor: constructor, index }); } /** * Unregisters a visualizer for a specified question type. @@ -46,12 +48,19 @@ export class VisualizationManager { questionTypes = Object.keys(VisualizationManager.vizualizers); } questionTypes.forEach(qType => { - let visualizers = VisualizationManager.vizualizers[qType]; - if (!!visualizers) { - let index = visualizers.indexOf(constructor); - if (index !== -1) { - visualizers.splice(index, 1); + if(constructor) { + let visualizers = VisualizationManager.vizualizers[qType]; + if (!!visualizers) { + const vDescr = visualizers.filter(v => v.ctor === constructor)[0]; + if(!!vDescr) { + let index = visualizers.indexOf(vDescr); + if (index !== -1) { + visualizers.splice(index, 1); + } + } } + } else { + VisualizationManager.vizualizers[qType] = []; } }); } @@ -69,11 +78,13 @@ export class VisualizationManager { public static getVisualizersByType( questionType: string ): VisualizerConstructor[] { - let visualizers = VisualizationManager.vizualizers[questionType]; - if (!visualizers) { + let vDescrs = VisualizationManager.vizualizers[questionType]; + if (!vDescrs) { return [VisualizerBase]; } - return visualizers; + vDescrs = [].concat(vDescrs); + vDescrs.sort((v1, v2) => v1.index - v2.index); + return vDescrs.map(v => v.ctor); } /** * Returns a constructor for an alternative visualizer selector. diff --git a/tests/visualizationManager.test.ts b/tests/visualizationManager.test.ts index b51907023..29d6bd8df 100644 --- a/tests/visualizationManager.test.ts +++ b/tests/visualizationManager.test.ts @@ -38,6 +38,8 @@ test("unregister visualizer", () => { expect(textVizualizers.length).toBe(1); expect(textVizualizers[0]).toBe(Text); + + VisualizationManager.registerVisualizer("text", WordCloud); }); test("unregister visualizer for all question types", () => { @@ -45,7 +47,6 @@ test("unregister visualizer for all question types", () => { const text = Text; // need to trigger VisualizationManager.registerVisualizer("text", Text); const wordCloud = WordCloud; // need to trigger VisualizationManager.registerVisualizer("text", WordCloud); - VisualizationManager.registerVisualizer("text", WordCloud); let textVizualizers = VisualizationManager.getVisualizersByType("text"); let commentVizualizers = VisualizationManager.getVisualizersByType("comment"); @@ -81,4 +82,39 @@ test("unregister visualizer for all question types", () => { expect(multipletextVizualizers.length).toBe(1); expect(multipletextVizualizers[0]).toBe(Text); + + VisualizationManager.registerVisualizer("text", WordCloud); + VisualizationManager.registerVisualizer("comment", WordCloud); + VisualizationManager.registerVisualizer("multipletext", WordCloud); }); + +test("visualizers default order", () => { + VisualizationManager.registerVisualizer("test", { name: "v1" } as any); + VisualizationManager.registerVisualizer("test", { name: "v2" } as any); + VisualizationManager.registerVisualizer("test", { name: "v3" } as any); + + let testVizualizers = VisualizationManager.getVisualizersByType("test"); + expect(testVizualizers.length).toBe(3); + expect(testVizualizers[0].name).toBe("v1"); + expect(testVizualizers[2].name).toBe("v3"); + + VisualizationManager.unregisterVisualizer("test", undefined as any); + testVizualizers = VisualizationManager.getVisualizersByType("test"); + expect(testVizualizers.length).toBe(0); +}); + +test("visualizers set order", () => { + VisualizationManager.registerVisualizer("test", { name: "v1" } as any); + VisualizationManager.registerVisualizer("test", { name: "v2" } as any); + VisualizationManager.registerVisualizer("test", { name: "v3" } as any, 0); + + let testVizualizers = VisualizationManager.getVisualizersByType("test"); + expect(testVizualizers.length).toBe(3); + expect(testVizualizers[0].name).toBe("v3"); + expect(testVizualizers[1].name).toBe("v1"); + expect(testVizualizers[2].name).toBe("v2"); + + VisualizationManager.unregisterVisualizer("test", undefined as any); + testVizualizers = VisualizationManager.getVisualizersByType("test"); + expect(testVizualizers.length).toBe(0); +}); \ No newline at end of file