From d882cfad1b8b2f49377458ce25dfafab5c2a4914 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 14:59:04 +0200 Subject: [PATCH 1/9] This fork is intended to allow passing the id of a DOM element rather than the element itself and let the plugin look for the elmement in document. This way you can use the plugin even when you need to pass options before the DOM is rendered --- README.md | 75 ++++++++++++++++++++++++++-- chartist-plugin-legend.js | 101 ++++++++++++++++++-------------------- package.json | 8 +-- test/test.legend.js | 14 +++--- 4 files changed, 133 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index e894493..97306c3 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,15 @@ Implements a legend for [Chartist](https://github.com/gionkunz/chartist-js) char **[Demo](https://codeyellowbv.github.io/chartist-plugin-legend/)** +## Why this Fork + +Since I needed to use this plugin with a Vue.js project and I needed to append the legend to a DOM element which wasn't yet rendered at the time the plugin was loaded, +I needed to be able to pass the id of the element and leave the trouble of retrieving the DOM element to the plugin itself. + ## Install ``` -$ npm install chartist-plugin-legend --save +$ npm install @matteoraf/chartist-plugin-legend --save ``` As styles are very different with each project, no CSS is included. You can copy paste this to use as base: @@ -55,6 +60,34 @@ As styles are very different with each project, no CSS is included. You can copy } ``` +If you are using this within a Vue.js component, you need to wrap it in a ` +``` + + ## Usage In an example chart: @@ -68,9 +101,45 @@ new Chartist.Bar('.ct-chart', data, { Chartist.plugins.legend() ] }, -}); +) +``` + +## Usage in a Vue.js project with the vue-chartist component + +Import the plugin together with chartist in a plugin file or in your main.js +```js +import Vue from 'vue' +import 'chartist/dist/chartist.min.css' +import 'chartist-plugin-legend/chartist-plugin-legend' + +Vue.use(require('vue-chartist')) +``` + +Then use it in any of your components the same way you'd normally do: + +```html + ``` +```js +data: {} +options: { + plugins: [ + this.$chartist.plugins.legend({...}), + ] + } +``` + +Then in your component + | __Option__ | __Description__ | __Type__ | __Default__ | | --- | --- | --- | --- | | `className` | Adds a class to the `ul` element. | `string` | `''` | @@ -79,4 +148,4 @@ new Chartist.Bar('.ct-chart', data, { | `onClick` | Accepts a function that gets invoked if `clickable` is true. The function has the `chart`, and the click event (`e`), as arguments. | `mixed` | `false` | | `classNames` | Accepts a array of strings as long as the chart's series, those will be added as classes to the `li` elements. | `mixed` | `false` | | `removeAll` | Allow all series to be removed at once. | `bool` | `false` | -| `position` | Sets the position of the legend element. `top`, `bottom` or any DOM2 Element are currently accepted. If a DOM Element is given, the legend will be appended as it's last child. | `'top'|'bottom'|HTMLElement` | `'top'` | +| `position` | Sets the position of the legend element. `top`, `bottom` or the `id` of any DOM2 Element are currently accepted. If a DOM Element is given, the legend will be appended as it's last child. | `string` | `'top'` | diff --git a/chartist-plugin-legend.js b/chartist-plugin-legend.js index a8dc67b..c646dc1 100644 --- a/chartist-plugin-legend.js +++ b/chartist-plugin-legend.js @@ -19,7 +19,7 @@ */ 'use strict'; - var defaultOptions = { + const defaultOptions = { className: '', classNames: false, removeAll: false, @@ -33,30 +33,19 @@ Chartist.plugins.legend = function (options) { - // Catch invalid options + // Catch invalid options - position must be a string if (options && options.position) { - if (!(options.position === 'top' || options.position === 'bottom' || options.position instanceof HTMLElement)) { + if (!(typeof options.position === 'string')) { throw Error('The position you entered is not a valid position'); } - if (options.position instanceof HTMLElement) { - // Detatch DOM element from options object, because Chartist.extend - // currently chokes on circular references present in HTMLElements - var cachedDOMPosition = options.position; - delete options.position; - } } options = Chartist.extend({}, defaultOptions, options); - if (cachedDOMPosition) { - // Reattatch the DOM Element position if it was removed before - options.position = cachedDOMPosition - } - return function legend(chart) { function removeLegendElement() { - var legendElement = chart.container.querySelector('.ct-legend'); + const legendElement = chart.container.querySelector('.ct-legend'); if (legendElement) { legendElement.parentNode.removeChild(legendElement); } @@ -77,7 +66,7 @@ } function createLegendElement() { - var legendElement = document.createElement('ul'); + const legendElement = document.createElement('ul'); legendElement.className = 'ct-legend'; if (chart instanceof Chartist.Pie) { legendElement.classList.add('ct-legend-inside'); @@ -99,8 +88,8 @@ // Initialize the array that associates series with legends. // -1 indicates that there is no legend associated with it. function initSeriesMetadata(useLabels) { - var seriesMetadata = new Array(chart.data.series.length); - for (var i = 0; i < chart.data.series.length; i++) { + const seriesMetadata = new Array(chart.data.series.length); + for (let i = 0; i < chart.data.series.length; i++) { seriesMetadata[i] = { data: chart.data.series[i], label: useLabels ? chart.data.labels[i] : null, @@ -111,7 +100,7 @@ } function createNameElement(i, legendText, classNamesViable) { - var li = document.createElement('li'); + const li = document.createElement('li'); li.classList.add('ct-series-' + i); // Append specific class to a legend element, if viable classes are given if (classNamesViable) { @@ -124,31 +113,37 @@ // Append the legend element to the DOM function appendLegendToDOM(legendElement) { - if (!(options.position instanceof HTMLElement)) { - switch (options.position) { - case 'top': - chart.container.insertBefore(legendElement, chart.container.childNodes[0]); - break; - - case 'bottom': - chart.container.insertBefore(legendElement, null); - break; - } - } else { - // Appends the legend element as the last child of a given HTMLElement - options.position.insertBefore(legendElement, null); + // If you named your div 'top' or 'bottom', it won't be attached + switch (options.position) { + case 'top': + chart.container.insertBefore(legendElement, chart.container.childNodes[0]); + break; + + case 'bottom': + chart.container.insertBefore(legendElement, null); + break; + + default: + const pos = document.getElementById(options.position) + if (pos !== null) { + // Appends the legend element as the last child of a given HTMLElement + pos.insertBefore(legendElement, null); + } else { + throw Error('The position you entered is not a valid position'); + } + break; } } function addClickHandler(legendElement, legends, seriesMetadata, useLabels) { legendElement.addEventListener('click', function(e) { - var li = e.target; + const li = e.target; if (li.parentNode !== legendElement || !li.hasAttribute('data-legend')) return; e.preventDefault(); - var legendIndex = parseInt(li.getAttribute('data-legend')); - var legend = legends[legendIndex]; + const legendIndex = parseInt(li.getAttribute('data-legend')); + const legend = legends[legendIndex]; if (!legend.active) { legend.active = true; @@ -157,22 +152,24 @@ legend.active = false; li.classList.add('inactive'); - var activeCount = legends.filter(function(legend) { return legend.active; }).length; - if (!options.removeAll && activeCount == 0) { + const activeCount = legends.filter(function (legend) { + return legend.active; + }).length; + if (!options.removeAll && activeCount === 0) { // If we can't disable all series at the same time, let's // reenable all of them: - for (var i = 0; i < legends.length; i++) { + for (let i = 0; i < legends.length; i++) { legends[i].active = true; legendElement.childNodes[i].classList.remove('inactive'); } } } - var newSeries = []; - var newLabels = []; + const newSeries = []; + const newLabels = []; - for (var i = 0; i < seriesMetadata.length; i++) { - if (seriesMetadata[i].legend != -1 && legends[seriesMetadata[i].legend].active) { + for (let i = 0; i < seriesMetadata.length; i++) { + if (seriesMetadata[i].legend !== -1 && legends[seriesMetadata[i].legend].active) { newSeries.push(seriesMetadata[i].data); newLabels.push(seriesMetadata[i].label); } @@ -193,21 +190,21 @@ removeLegendElement(); - var legendElement = createLegendElement(); - var useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length; - var legendNames = getLegendNames(useLabels); - var seriesMetadata = initSeriesMetadata(useLabels); - var legends = []; + const legendElement = createLegendElement(); + const useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length; + const legendNames = getLegendNames(useLabels); + const seriesMetadata = initSeriesMetadata(useLabels); + const legends = []; // Check if given class names are viable to append to legends - var classNamesViable = Array.isArray(options.classNames) && options.classNames.length === legendNames.length; + const classNamesViable = Array.isArray(options.classNames) && options.classNames.length === legendNames.length; // Loop through all legends to set each name in a list item. legendNames.forEach(function (legend, i) { - var legendText = legend.name || legend; - var legendSeries = legend.series || [i]; + const legendText = legend.name || legend; + const legendSeries = legend.series || [i]; - var li = createNameElement(i, legendText, classNamesViable); + const li = createNameElement(i, legendText, classNamesViable); legendElement.appendChild(li); legendSeries.forEach(function(seriesIndex) { @@ -221,7 +218,7 @@ }); }); - chart.on('created', function (data) { + chart.on('created', function () { appendLegendToDOM(legendElement); }); diff --git a/package.json b/package.json index c19a0b0..e64556b 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { - "name": "chartist-plugin-legend", - "version": "0.6.2", - "author": "Kees Kluskens ", + "name": "@matteoraf/chartist-plugin-legend", + "version": "0.7.0", + "author": "Matteoraf & Kees Kluskens ", "description": "Legend plugin for Chartist.js.", "license": "ISC", "repository": { "type": "git", - "url": "https://github.com/CodeYellowBV/chartist-plugin-legend" + "url": "https://github.com/matteoraf/chartist-plugin-legend" }, "main": "chartist-plugin-legend.js", "files": [ diff --git a/test/test.legend.js b/test/test.legend.js index 7a56158..32263eb 100644 --- a/test/test.legend.js +++ b/test/test.legend.js @@ -304,10 +304,12 @@ describe('Chartist plugin legend', function() { }); it('should allow positioning to any DOM2 element', function (done) { + const elementId = 'legend' var testDOMElement = document.createElement('div'); + testDOMElement.setAttribute('id', elementId) document.body.insertBefore(testDOMElement , null); - chart = generateChart('Line', chartDataLine, { position: testDOMElement }); + chart = generateChart('Line', chartDataLine, { position: elementId }); // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler chart.on('created', function () { @@ -435,14 +437,14 @@ describe('Chartist plugin legend', function() { click(seriesB); expect(chart.legendClicked).to.equal(true); - + //Clicking on an inactive series should also call the function. chart.legendClicked = false; click(seriesB); expect(chart.legendClicked).to.equal(true); }); }); - + describe('clickable with multiple series per legend item', function() { before(function(done) { chart = generateChart('Line', chartDataLine, { @@ -490,7 +492,7 @@ describe('Chartist plugin legend', function() { expect(svgSeries2[0].className.baseVal).to.contain('ct-series-a'); expect(svgSeries2[1].className.baseVal).to.contain('ct-series-b'); expect(svgSeries2[2].className.baseVal).to.contain('ct-series-c'); - + // Clicking on the first legend item should hide the two first series: click(seriesA); expect(chart.data.series.length).to.equal(1); @@ -549,14 +551,14 @@ describe('Chartist plugin legend', function() { click(seriesB); expect(chart.legendClicked).to.equal(true); - + //Clicking on an inactive series should also call the function. chart.legendClicked = false; click(seriesB); expect(chart.legendClicked).to.equal(true); }); }); - + describe('clickable for a pie', function() { before(function(done) { chart = generateChart('Pie', chartDataPie, { From fbb86dfec9272caef481b96095f304cb93340066 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 15:16:15 +0200 Subject: [PATCH 2/9] fixed README.md travis --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 97306c3..08441be 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # chartist-plugin-legend -[![Build Status](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend) -[![Coverage Status](https://coveralls.io/repos/github/CodeYellowBV/chartist-plugin-legend/badge.svg?branch=master)](https://coveralls.io/github/CodeYellowBV/chartist-plugin-legend?branch=master) +[![Build Status](https://travis-ci.org/matteoraf/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend) Implements a legend for [Chartist](https://github.com/gionkunz/chartist-js) charts. From d4e244bb283e9f4f42f12adc955bed0dfc7b9e7e Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 15:16:52 +0200 Subject: [PATCH 3/9] fixed README.md travis --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 08441be..cbcce43 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # chartist-plugin-legend -[![Build Status](https://travis-ci.org/matteoraf/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend) +[![Build Status](https://travis-ci.org/matteoraf/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/matteoraf/chartist-plugin-legend) Implements a legend for [Chartist](https://github.com/gionkunz/chartist-js) charts. From 04e412d9b793bea3975537c541610df26f04e771 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 15:23:51 +0200 Subject: [PATCH 4/9] Phantomjs doesn't support ES6, switch back to ES5 --- test/test.legend.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test.legend.js b/test/test.legend.js index 32263eb..7713a3d 100644 --- a/test/test.legend.js +++ b/test/test.legend.js @@ -174,8 +174,8 @@ describe('Chartist plugin legend', function() { after(destroyChart); it('should create unique legends', function () { - const legendText1 = chart.container.querySelector('ul.ct-legend').textContent; - const legendText2 = chart2.container.querySelector('ul.ct-legend').textContent; + var legendText1 = chart.container.querySelector('ul.ct-legend').textContent; + var legendText2 = chart2.container.querySelector('ul.ct-legend').textContent; expect(legendText1).to.equal('Blue pillRed pillPurple pill'); expect(legendText2).to.equal('Second pill'); }); @@ -304,7 +304,7 @@ describe('Chartist plugin legend', function() { }); it('should allow positioning to any DOM2 element', function (done) { - const elementId = 'legend' + var elementId = 'legend' var testDOMElement = document.createElement('div'); testDOMElement.setAttribute('id', elementId) document.body.insertBefore(testDOMElement , null); From 12a8275dce1c66a65b32125c927fd69b02a89916 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 16:20:46 +0200 Subject: [PATCH 5/9] Phantomjs doesn't support ES6, switch back to ES5 --- chartist-plugin-legend.js | 50 +++---- test/test.legend.js | 307 +++++++++++++++++++------------------- 2 files changed, 180 insertions(+), 177 deletions(-) diff --git a/chartist-plugin-legend.js b/chartist-plugin-legend.js index c646dc1..2518767 100644 --- a/chartist-plugin-legend.js +++ b/chartist-plugin-legend.js @@ -19,7 +19,7 @@ */ 'use strict'; - const defaultOptions = { + var defaultOptions = { className: '', classNames: false, removeAll: false, @@ -45,7 +45,7 @@ return function legend(chart) { function removeLegendElement() { - const legendElement = chart.container.querySelector('.ct-legend'); + var legendElement = chart.container.querySelector('.ct-legend'); if (legendElement) { legendElement.parentNode.removeChild(legendElement); } @@ -66,7 +66,7 @@ } function createLegendElement() { - const legendElement = document.createElement('ul'); + var legendElement = document.createElement('ul'); legendElement.className = 'ct-legend'; if (chart instanceof Chartist.Pie) { legendElement.classList.add('ct-legend-inside'); @@ -88,8 +88,8 @@ // Initialize the array that associates series with legends. // -1 indicates that there is no legend associated with it. function initSeriesMetadata(useLabels) { - const seriesMetadata = new Array(chart.data.series.length); - for (let i = 0; i < chart.data.series.length; i++) { + var seriesMetadata = new Array(chart.data.series.length); + for (var i = 0; i < chart.data.series.length; i++) { seriesMetadata[i] = { data: chart.data.series[i], label: useLabels ? chart.data.labels[i] : null, @@ -100,7 +100,7 @@ } function createNameElement(i, legendText, classNamesViable) { - const li = document.createElement('li'); + var li = document.createElement('li'); li.classList.add('ct-series-' + i); // Append specific class to a legend element, if viable classes are given if (classNamesViable) { @@ -124,7 +124,7 @@ break; default: - const pos = document.getElementById(options.position) + var pos = document.getElementById(options.position) if (pos !== null) { // Appends the legend element as the last child of a given HTMLElement pos.insertBefore(legendElement, null); @@ -137,13 +137,13 @@ function addClickHandler(legendElement, legends, seriesMetadata, useLabels) { legendElement.addEventListener('click', function(e) { - const li = e.target; + var li = e.target; if (li.parentNode !== legendElement || !li.hasAttribute('data-legend')) return; e.preventDefault(); - const legendIndex = parseInt(li.getAttribute('data-legend')); - const legend = legends[legendIndex]; + var legendIndex = parseInt(li.getAttribute('data-legend')); + var legend = legends[legendIndex]; if (!legend.active) { legend.active = true; @@ -152,23 +152,23 @@ legend.active = false; li.classList.add('inactive'); - const activeCount = legends.filter(function (legend) { + var activeCount = legends.filter(function (legend) { return legend.active; }).length; if (!options.removeAll && activeCount === 0) { - // If we can't disable all series at the same time, let's + // If we can't disable all series at the same time, var's // reenable all of them: - for (let i = 0; i < legends.length; i++) { + for (var i = 0; i < legends.length; i++) { legends[i].active = true; legendElement.childNodes[i].classList.remove('inactive'); } } } - const newSeries = []; - const newLabels = []; + var newSeries = []; + var newLabels = []; - for (let i = 0; i < seriesMetadata.length; i++) { + for (var i = 0; i < seriesMetadata.length; i++) { if (seriesMetadata[i].legend !== -1 && legends[seriesMetadata[i].legend].active) { newSeries.push(seriesMetadata[i].data); newLabels.push(seriesMetadata[i].label); @@ -190,21 +190,21 @@ removeLegendElement(); - const legendElement = createLegendElement(); - const useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length; - const legendNames = getLegendNames(useLabels); - const seriesMetadata = initSeriesMetadata(useLabels); - const legends = []; + var legendElement = createLegendElement(); + var useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length; + var legendNames = getLegendNames(useLabels); + var seriesMetadata = initSeriesMetadata(useLabels); + var legends = []; // Check if given class names are viable to append to legends - const classNamesViable = Array.isArray(options.classNames) && options.classNames.length === legendNames.length; + var classNamesViable = Array.isArray(options.classNames) && options.classNames.length === legendNames.length; // Loop through all legends to set each name in a list item. legendNames.forEach(function (legend, i) { - const legendText = legend.name || legend; - const legendSeries = legend.series || [i]; + var legendText = legend.name || legend; + var legendSeries = legend.series || [i]; - const li = createNameElement(i, legendText, classNamesViable); + var li = createNameElement(i, legendText, classNamesViable); legendElement.appendChild(li); legendSeries.forEach(function(seriesIndex) { diff --git a/test/test.legend.js b/test/test.legend.js index 7713a3d..7991770 100644 --- a/test/test.legend.js +++ b/test/test.legend.js @@ -22,7 +22,7 @@ var chartDataPie = { }; // PhantomJS can't do a `.click()` on a DOM element, this is a workaround. -function click(el){ +function click(el) { var ev = document.createEvent('MouseEvent'); ev.initMouseEvent( 'click', @@ -48,7 +48,7 @@ function generateChart(type, chartData, legendOptions, chartNumber) { }); } -describe('Chartist plugin legend', function() { +describe('Chartist plugin legend', function () { var chart; var chart2; @@ -67,7 +67,7 @@ describe('Chartist plugin legend', function() { expect(window.Chartist.plugins.legend).to.exist; }); - before(function() { + before(function () { var chartEl = document.createElement('div'); chartEl.classList.add('ct-chart-1'); document.body.appendChild(chartEl); @@ -76,11 +76,13 @@ describe('Chartist plugin legend', function() { document.body.appendChild(chartEl2); }); - describe('work with a Line chart', function() { - before(function(done) { + describe('work with a Line chart', function () { + before(function (done) { chart = generateChart('Line', chartDataLine); - chart.on('created', function() { done(); }); + chart.on('created', function () { + done(); + }); }); after(destroyChart); @@ -99,7 +101,7 @@ describe('Chartist plugin legend', function() { var legendKey = 0; var parent = chart.container.querySelector('ul.ct-legend'); - [].forEach.call(parent.childNodes, function(item) { + [].forEach.call(parent.childNodes, function (item) { expect(item.dataset.legend).to.equal(String(legendKey)); expect(item.className).to.equal('ct-series-' + String(legendKey)); expect(item.innerHTML).to.equal(chartDataLine.series[legendKey].name); @@ -115,20 +117,22 @@ describe('Chartist plugin legend', function() { window.Chartist.plugins.legend()(chart); // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler chart.on('created', function () { - setTimeout(function () { - var matches = chart.container.querySelectorAll('ul.ct-legend'); - expect(matches.length).to.equal(1); + setTimeout(function () { + var matches = chart.container.querySelectorAll('ul.ct-legend'); + expect(matches.length).to.equal(1); - }, 10) + }, 10) }); }); }); - describe('work with a Pie chart', function() { - before(function(done) { + describe('work with a Pie chart', function () { + before(function (done) { chart = generateChart('Pie', chartDataPie); - chart.on('created', function() { done(); }); + chart.on('created', function () { + done(); + }); }); after(destroyChart); @@ -148,7 +152,7 @@ describe('Chartist plugin legend', function() { var legendKey = 0; var parent = chart.container.querySelector('ul.ct-legend'); - [].forEach.call(parent.childNodes, function(item) { + [].forEach.call(parent.childNodes, function (item) { expect(item.dataset.legend).to.equal(String(legendKey)); expect(item.className).to.equal('ct-series-' + String(legendKey)); expect(item.innerHTML).to.equal(chartDataPie.labels[legendKey]); @@ -157,14 +161,14 @@ describe('Chartist plugin legend', function() { }); }); - describe('work with two legends', function() { - before(function(done) { + describe('work with two legends', function () { + before(function (done) { chart = generateChart('Line', chartDataLine); - chart.on('created', function() { + chart.on('created', function () { chart.off('created'); chart2 = generateChart('Line', chart2DataLine, null, 2); - chart2.on('created', function() { + chart2.on('created', function () { chart2.off('created'); done(); }); @@ -181,34 +185,33 @@ describe('Chartist plugin legend', function() { }); }); - describe('allow options', function() { - it('should use custom legend names if provided', function(done) { + describe('allow options', function () { + it('should use custom legend names if provided', function (done) { var legendNames = ['Sheep', 'are', 'animals']; - chart = generateChart('Line', chartDataLine, { legendNames: legendNames }); + chart = generateChart('Line', chartDataLine, {legendNames: legendNames}); // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler chart.on('created', function () { - setTimeout(function () { - var legendKey = 0; - var parent = chart.container.querySelector('ul.ct-legend'); + setTimeout(function () { + var legendKey = 0; + var parent = chart.container.querySelector('ul.ct-legend'); - expect(parent.childNodes.length).to.equal(3); - [].forEach.call(parent.childNodes, function (item) - { - expect(item.innerHTML).to.equal(legendNames[legendKey]); - legendKey += 1; - }); + expect(parent.childNodes.length).to.equal(3); + [].forEach.call(parent.childNodes, function (item) { + expect(item.innerHTML).to.equal(legendNames[legendKey]); + legendKey += 1; + }); - destroyChart(); - done(); + destroyChart(); + done(); - }, 10) + }, 10) }); }); it('should use the data object name when labels are not defined', function (done) { var chartDataNoLabels = { - labels: [], // adding empty arry because chartist.js converts null or undefined labels into empty array + labels: [], // adding empty array because chartist.js converts null or undefined labels into empty array series: [ {name: 'Piece A', value: 20}, {name: 'Piece B', value: 10}, @@ -219,14 +222,14 @@ describe('Chartist plugin legend', function() { chart = generateChart('Pie', chartDataNoLabels); // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler - chart.on('created', function() { + chart.on('created', function () { setTimeout(function () { var legendKey = 0; var parent = chart.container.querySelector('ul.ct-legend'); expect(parent.childNodes.length).to.equal(4); - [].forEach.call(parent.childNodes, function(item) { + [].forEach.call(parent.childNodes, function (item) { expect(item.innerHTML).to.equal(chartDataNoLabels.series[legendKey].name); legendKey += 1; }); @@ -239,119 +242,119 @@ describe('Chartist plugin legend', function() { }); - it('should allow a custom class name', function(done) { - chart = generateChart('Line', chartDataLine, { className: 'bananas' }); + it('should allow a custom class name', function (done) { + chart = generateChart('Line', chartDataLine, {className: 'bananas'}); // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler chart.on('created', function () { - setTimeout(function () { - var legend = chart.container.querySelector('ul.ct-legend'); - expect(legend.classList[1]).to.equal('bananas'); - destroyChart(); - done(); + setTimeout(function () { + var legend = chart.container.querySelector('ul.ct-legend'); + expect(legend.classList[1]).to.equal('bananas'); + destroyChart(); + done(); - }, 10) + }, 10) }); }); it('should allow multiple custom class names', function (done) { - var classNames = ['multiclass-0', 'multiclass-1', 'multiclass-hidden']; - chart = generateChart('Line', chartDataLine, { classNames: classNames }); - - // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler - chart.on('created', function () { - setTimeout(function () { - var legend = chart.container.querySelector('ul.ct-legend'); - - expect(chart.data.series.length).to.equal(3); - expect(legend.children[0].classList.contains(classNames[0])).to.be.true; - expect(legend.children[1].classList.contains(classNames[1])).to.be.true; - expect(legend.children[2].classList.contains(classNames[2])).to.be.true; - destroyChart(); - done(); - - }, 10) - }); + var classNames = ['multiclass-0', 'multiclass-1', 'multiclass-hidden']; + chart = generateChart('Line', chartDataLine, {classNames: classNames}); + + // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler + chart.on('created', function () { + setTimeout(function () { + var legend = chart.container.querySelector('ul.ct-legend'); + + expect(chart.data.series.length).to.equal(3); + expect(legend.children[0].classList.contains(classNames[0])).to.be.true; + expect(legend.children[1].classList.contains(classNames[1])).to.be.true; + expect(legend.children[2].classList.contains(classNames[2])).to.be.true; + destroyChart(); + done(); + + }, 10) + }); }); describe('allow custom positioning', function () { - it('should allow top positioning', function (done) { - chart = generateChart('Line', chartDataLine, { position: 'top' }); - - // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler - chart.on('created', function () { - setTimeout(function () { - expect(chart.container.childNodes.length).to.equal(2); - var listElement = chart.container.querySelector("ul"); - expect(chart.container.childNodes[0]).to.equal(listElement); - done(); - }, 10) - }); - }); - - it('should allow bottom positioning', function (done) { - chart = generateChart('Line', chartDataLine, { position: 'bottom' }); - - // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler - chart.on('created', function () { - setTimeout(function () { - expect(chart.container.childNodes.length).to.equal(2); - var listElement = chart.container.querySelector("ul"); - expect(chart.container.childNodes[1]).to.equal(listElement); - done(); - }, 10) - }); - }); - - it('should allow positioning to any DOM2 element', function (done) { - var elementId = 'legend' - var testDOMElement = document.createElement('div'); - testDOMElement.setAttribute('id', elementId) - document.body.insertBefore(testDOMElement , null); - - chart = generateChart('Line', chartDataLine, { position: elementId }); - - // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler - chart.on('created', function () { - setTimeout(function () { - expect(testDOMElement.childNodes.length).to.equal(1); - var listElement = testDOMElement.querySelector("ul"); - expect(testDOMElement.childNodes[0]).to.equal(listElement); - - // Clean up - document.body.removeChild(testDOMElement); - done(); - }, 100) - }); - }); + it('should allow top positioning', function (done) { + chart = generateChart('Line', chartDataLine, {position: 'top'}); + + // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler + chart.on('created', function () { + setTimeout(function () { + expect(chart.container.childNodes.length).to.equal(2); + var listElement = chart.container.querySelector("ul"); + expect(chart.container.childNodes[0]).to.equal(listElement); + done(); + }, 10) + }); + }); + + it('should allow bottom positioning', function (done) { + chart = generateChart('Line', chartDataLine, {position: 'bottom'}); + + // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler + chart.on('created', function () { + setTimeout(function () { + expect(chart.container.childNodes.length).to.equal(2); + var listElement = chart.container.querySelector("ul"); + expect(chart.container.childNodes[1]).to.equal(listElement); + done(); + }, 10) + }); + }); + + it('should allow positioning to any DOM2 element', function (done) { + var elementId = 'legend' + var testDOMElement = document.createElement('div'); + testDOMElement.setAttribute('id', elementId) + document.body.insertBefore(testDOMElement, null); + + chart = generateChart('Line', chartDataLine, {position: elementId}); + + // Set a delay on the test to ensure it doesn't overlap with the plugin native 'created' handler + chart.on('created', function () { + setTimeout(function () { + expect(testDOMElement.childNodes.length).to.equal(1); + var listElement = testDOMElement.querySelector("ul"); + expect(testDOMElement.childNodes[0]).to.equal(listElement); + + // Clean up + document.body.removeChild(testDOMElement); + done(); + }, 100) + }); + }); }); it('should allow to remove all series at once', function () { - chart = generateChart('Line', chart2DataLine, { removeAll: true }); - - chart.on('created', function () { - var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); - - expect(chart.data.series.length).to.equal(1); - click(seriesA); - expect(chart.data.series.length).to.equal(0); - click(seriesA); - expect(chart.data.series.length).to.equal(1); - destroyChart(); - done(); - }); + chart = generateChart('Line', chart2DataLine, {removeAll: true}); + + chart.on('created', function () { + var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); + + expect(chart.data.series.length).to.equal(1); + click(seriesA); + expect(chart.data.series.length).to.equal(0); + click(seriesA); + expect(chart.data.series.length).to.equal(1); + destroyChart(); + done(); + }); }) - describe('clickable', function() { - before(function(done) { + describe('clickable', function () { + before(function (done) { chart = generateChart('Line', chartDataLine, { clickable: true, - onClick: function(chart,e) { + onClick: function (chart) { chart.legendClicked = true; } }); - chart.on('created', function() { + chart.on('created', function () { chart.off('created'); done(); }); @@ -359,13 +362,13 @@ describe('Chartist plugin legend', function() { after(destroyChart); - it('should enforce a className for each series', function() { + it('should enforce a className for each series', function () { expect(chart.data.series[0].className).to.equal('ct-series-a'); expect(chart.data.series[1].className).to.equal('ct-series-b'); expect(chart.data.series[2].className).to.equal('ct-series-c'); }); - it('should hide a series after a click on the legend item', function() { + it('should hide a series after a click on the legend item', function () { var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); var seriesC = chart.container.querySelector('ul.ct-legend > .ct-series-2'); @@ -402,7 +405,7 @@ describe('Chartist plugin legend', function() { expect(svgSeries2[2].className.baseVal).to.contain('ct-series-c'); }); - it('should update the legend item classes', function() { + it('should update the legend item classes', function () { var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); var seriesC = chart.container.querySelector('ul.ct-legend > .ct-series-2'); @@ -422,17 +425,17 @@ describe('Chartist plugin legend', function() { // A click in the last active series should set all series active again. click(seriesA); click(seriesB); - var legendItems = chart.container.querySelectorAll('ul.ct-legend > li'); + legendItems = chart.container.querySelectorAll('ul.ct-legend > li'); expect(legendItems[0].className).to.equal('ct-series-0 inactive'); expect(legendItems[1].className).to.equal('ct-series-1 inactive'); expect(legendItems[2].className).to.equal('ct-series-2'); click(seriesC); - var inactiveItem = chart.container.querySelectorAll('ul.ct-legend > li.inactive'); + inactiveItem = chart.container.querySelectorAll('ul.ct-legend > li.inactive'); expect(inactiveItem.length).to.equal(0); }); - it('should call a function after a click on the legend item', function() { + it('should call a function after a click on the legend item', function () { var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); click(seriesB); @@ -445,17 +448,17 @@ describe('Chartist plugin legend', function() { }); }); - describe('clickable with multiple series per legend item', function() { - before(function(done) { + describe('clickable with multiple series per legend item', function () { + before(function (done) { chart = generateChart('Line', chartDataLine, { clickable: true, - onClick: function(chart,e) { + onClick: function (chart) { chart.legendClicked = true; }, - legendNames: [{name: 'Red-ish', series: [0,1]}, {name: 'Yellow', series: [2]}] + legendNames: [{name: 'Red-ish', series: [0, 1]}, {name: 'Yellow', series: [2]}] }); - chart.on('created', function() { + chart.on('created', function () { chart.off('created'); done(); }); @@ -463,13 +466,13 @@ describe('Chartist plugin legend', function() { after(destroyChart); - it('should enforce a className for each series', function() { + it('should enforce a className for each series', function () { expect(chart.data.series[0].className).to.equal('ct-series-a'); expect(chart.data.series[1].className).to.equal('ct-series-b'); expect(chart.data.series[2].className).to.equal('ct-series-c'); }); - it('should hide a series after a click on the legend item', function() { + it('should hide a series after a click on the legend item', function () { var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); @@ -497,13 +500,13 @@ describe('Chartist plugin legend', function() { click(seriesA); expect(chart.data.series.length).to.equal(1); expect(chart.data.series[0].name).to.equal('Purple pill'); - var svgSeries = chart.container.querySelectorAll('g.ct-series'); + svgSeries = chart.container.querySelectorAll('g.ct-series'); expect(svgSeries.length).to.equal(1); expect(svgSeries[0].className.baseVal).to.contain('ct-series-c'); // A second click should show the both series again. click(seriesA); - var svgSeries2 = chart.container.querySelectorAll('g.ct-series'); + svgSeries2 = chart.container.querySelectorAll('g.ct-series'); expect(svgSeries2.length).to.equal(3); expect(svgSeries2[0].className.baseVal).to.contain('ct-series-a'); expect(svgSeries2[1].className.baseVal).to.contain('ct-series-b'); @@ -520,7 +523,7 @@ describe('Chartist plugin legend', function() { expect(svgSeries2[2].className.baseVal).to.contain('ct-series-c'); }); - it('should update the legend item classes', function() { + it('should update the legend item classes', function () { var seriesA = chart.container.querySelector('ul.ct-legend > .ct-series-0'); var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); @@ -537,16 +540,16 @@ describe('Chartist plugin legend', function() { // A click in the last active series should set all series active again. click(seriesA); - var legendItems = chart.container.querySelectorAll('ul.ct-legend > li'); + legendItems = chart.container.querySelectorAll('ul.ct-legend > li'); expect(legendItems[0].className).to.equal('ct-series-0 inactive'); expect(legendItems[1].className).to.equal('ct-series-1'); click(seriesB); - var inactiveItem = chart.container.querySelectorAll('ul.ct-legend > li.inactive'); + inactiveItem = chart.container.querySelectorAll('ul.ct-legend > li.inactive'); expect(inactiveItem.length).to.equal(0); }); - it('should call a function after a click on the legend item', function() { + it('should call a function after a click on the legend item', function () { var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); click(seriesB); @@ -559,13 +562,13 @@ describe('Chartist plugin legend', function() { }); }); - describe('clickable for a pie', function() { - before(function(done) { + describe('clickable for a pie', function () { + before(function (done) { chart = generateChart('Pie', chartDataPie, { clickable: true, }); - chart.on('created', function() { + chart.on('created', function () { chart.off('created'); done(); }); @@ -573,12 +576,12 @@ describe('Chartist plugin legend', function() { after(destroyChart); - it('should enforce a className for each series', function() { + it('should enforce a className for each series', function () { expect(chart.data.series[0].className).to.equal('ct-series-a'); expect(chart.data.series[1].className).to.equal('ct-series-b'); }); - it('should hide a series after a click on the legend item', function() { + it('should hide a series after a click on the legend item', function () { var seriesB = chart.container.querySelector('ul.ct-legend > .ct-series-1'); expect(chart.data.labels.length).to.equal(4); From 45437ccd9b4f9ab7bede4c1f4017d2432510eaf7 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 16:33:12 +0200 Subject: [PATCH 6/9] added .idea/ to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 25fbf5a..c6f71ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ coverage/ +.idea/ From 98fc9f8d3a0fb8815f8c80e0514b830797a91b77 Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 16:53:16 +0200 Subject: [PATCH 7/9] fix README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cbcce43..85648ab 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Import the plugin together with chartist in a plugin file or in your main.js ```js import Vue from 'vue' import 'chartist/dist/chartist.min.css' -import 'chartist-plugin-legend/chartist-plugin-legend' +import '@matteoraf/chartist-plugin-legend/chartist-plugin-legend' Vue.use(require('vue-chartist')) ``` From 9987a017cd23f85dbe174684622688c5e7b042af Mon Sep 17 00:00:00 2001 From: matraf Date: Fri, 15 May 2020 17:02:36 +0200 Subject: [PATCH 8/9] Prepare for pull request --- README.md | 48 ++++-------------------------------------------- package.json | 4 ++-- 2 files changed, 6 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 85648ab..705efe5 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,16 @@ # chartist-plugin-legend -[![Build Status](https://travis-ci.org/matteoraf/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/matteoraf/chartist-plugin-legend) +[![Build Status](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend.svg?branch=master)](https://travis-ci.org/CodeYellowBV/chartist-plugin-legend) +[![Coverage Status](https://coveralls.io/repos/github/CodeYellowBV/chartist-plugin-legend/badge.svg?branch=master)](https://coveralls.io/github/CodeYellowBV/chartist-plugin-legend?branch=master) Implements a legend for [Chartist](https://github.com/gionkunz/chartist-js) charts. **[Demo](https://codeyellowbv.github.io/chartist-plugin-legend/)** -## Why this Fork - -Since I needed to use this plugin with a Vue.js project and I needed to append the legend to a DOM element which wasn't yet rendered at the time the plugin was loaded, -I needed to be able to pass the id of the element and leave the trouble of retrieving the DOM element to the plugin itself. - ## Install ``` -$ npm install @matteoraf/chartist-plugin-legend --save +$ npm install chartist-plugin-legend --save ``` As styles are very different with each project, no CSS is included. You can copy paste this to use as base: @@ -60,7 +56,7 @@ As styles are very different with each project, no CSS is included. You can copy ``` If you are using this within a Vue.js component, you need to wrap it in a `